python学习笔记

# 这是注释 Ctrl + /
# 这也是注释  ...  注释内容    ...
import tkinter.messagebox
import types  # 添加动态方法的库
'''
print('你好,python')
a='hp'
b='sb'
print(a)
print("周旭飞是一个:")
print(a)
print(1+1)
print(57%2)
print(2 and 1)
'''
'''
算术运算符:**指数,//地板除
逻辑运算符:and  or not非
type()查看变量类型
'''
'''
# 输出:%占位符  ,换行:\n  没有%c,统一用%s
name='章鱼丸'
classPro='xx大学大一3班'
age=7
print('我的名字是%s:来自【%s】 今年%d岁了'%(name,classPro,age))  # 注意格式
print('--------- -------------')

# 格式输出其它的方式:  .format()
print('姓名:{}  年龄:{}'.format(name,age))
'''
'''
# 输入 input获取键盘输入,输入结果都是str类型,如果接收数字类型需要转换为int
name=input('请输入你的姓名:')
QQ=input('请输入你的QQ:')
age=int(input('请输入的年龄:'))  # 强制类型转换
print('\n')
print('你的姓名:{}'.format(name))
print('你的QQ:{}'.format(QQ))
print('你的年龄:%d'%age)
'''

# 流程:是计算机执行代码的顺序
# 流程控制:对代码执行的顺序进行有效的管理,只有流程控制才能实现在开发当中的业务逻辑


'''
流程控制分类:    与C语言差球不多
    顺序流程
    选择流程/分支流程 :
        1.单分支:
            if 条件表达式: 
                代码指令
                ....
        2.双分支:
            if 条件表达式:
                代码指令
            else:
                代码指令
        3.多分支:
            if 条件表达式:
                ....       可以是多条
            elif 条件表达式:
                ....
            elif 条件表达式:
                ....
            else:
                ....        
    循环流程:
        while 条件表达式:
             .....
        for ...  in 可迭代集合对象:
            .....
'''
# 选择流程:

# score=80
# 单分支:
'''
if score<=60:
    print('成绩不太理想,要继续加油')
    pass  # 空语句 或者表示代码块结束
'''

# 双分支:
'''
if score<=60:
    print('成绩不太理想,要继续加油')
    pass
else:
    print('成绩不错,继续努力')
    pass
'''

# 多分支:
'''
score=int(input('请输入你的成绩:'))
if score>=80:
    print('A等级')
    pass
elif score>=70:
    print('B等级')
    pass
elif score>=60:
    print('C等级')
    pass
else:
    print('可以回家种地了....')
    pass
'''

# 嵌套:
'''
    if 条件:
        if 条件:
            ...
        else:
            ...
    elif 条件:
        if 条件:
            ...
        else:
            ...
    else:
        ...
        
        
# 猜拳小游戏:
# 0:石头 1:剪刀 2:布
import random
# 计算机  人
print('猜拳游戏:  0:石头 1:剪刀 2:布\n')
person=int(input('请出拳:'))
computer=random.randint(0,2)  # 表示生成0-2的随机数字,包括0和2,int类型
if person==0 and computer==1:
    print('you win!')
    pass
elif person==1 and computer==2:
    print('you win!')
    pass
elif person==2 and computer==0:
    print('you win!')
    pass
elif person==computer:
    print('平手!')
    pass
else:
    print('you lost!')
            '''


# 循环:
'''
# while 语法结构:
        while 条件表达式:
            代码指令
特点:
1.有初始值
2.条件表达式
3.变量【循环体内计数变量】的自增自减
条件:循环的次数不确定
              
# 打印乘法表:  while的嵌套
j = 9
while j >= 1:
    i = 1
    while i <= j:
        print('%d*%d=%2d'%(i,j,i*j),end=' ') # end= 不让他换行
        i += 1
        pass
    j -= 1
    print() # 换行
    pass
        '''

# for循环:结构
# 语法特点:遍历操作,依次取集合容器中的每一个值:
#     for 临时变量 in 容器(字符串,列表等):
#         执行代码块
tags = '我是一个中国人' # 字符串就是字符类型的集合
for item in tags:
    print(item,end='')
    pass

# range 这个函数可以生成一个数据集合列表
# range(起始:结束:步长)  步长就是多长取一个值,为1可以省略,步长不能为0
su=0
for data in range(1,101):   # 左包含右不包含
    su += data
    pass
print(su)

# braek  continue  和C语言的一样
# braek  continue  和C语言的一样
# braek  continue  和C语言的一样


# 猜年龄小游戏,三个要求
#     1.允许用户最多尝试3次
#     2.每次尝试3次后,如果没有猜对,就问用户是否还想继续玩,如果回答Y或者y,就继续让其猜3次,以此往复,如果回答N或n,就退出程序
#     3.如何猜对了,就直接退出
'''
count = 1
times = 3
tag = 0
import random  # 声明
age = random.randint(0,100)
while 0<1:
    while count <= times:
        answer = int(input('请输入您的猜测:'))
        if answer != age:
            count += 1
            if answer > age:
                print('answer is bigger than correct answer, try again!')
                pass
            else:
                print('answer is smaller than correct answer, try again!')
                pass
            pass
        else:
            print('you win!')
            tag = 1
            break
        pass
    if tag == 0:
        print('you lost!')
        answer = input('是否还想继续玩?【回答yes或者no】\n')
        if answer == 'yes':
            count = 1
            continue
            pass
        else:
            break
            pass
    else:
        break
        pass
    '''

# 小王身高1.75,体重80.5kg。请根据MBI公式(体重除以身高的平方)帮小王计算它的BMI指数,并根据MBI指数:
#     低于18.5  过轻
#     18.5 - 25 正常
#     25 - 28 过重
#     28 - 32 肥胖
#     高于32: 严重肥胖
#     用if-elif判断并打印结果
'''
BMI_index = 80.5 / (1.75**2)
if BMI_index < 18.5:
    print('过轻')
    pass
elif (BMI_index >=25) and (BMI_index <25):
    print('正常')
    pass
elif (BMI_index >=25) and (BMI_index <28):
    print('过重')
    pass
elif (BMI_index >=28) and (BMI_index <32):
    print('肥胖')
    pass
else:
    print('严重肥胖')
    pass
         '''

'''
序列:一组按照顺序排列的值【数据集合】   字符串,列表,元组
    优点:支持索引和切片的操作  
    特征:第一个正索引为0,指向的是左端,第一个索引为负数的时候,指向的是右端

切片:【高级特性】可以根据下标来获取序列对象的任意[部分]数据
    语法结构:[开始的下标start:结束的下标end:步长step]  没有写步长时,默认步长为1   start <= value     ***下标会越界,切片不会!!!
    
字符串操作:
    常用函数:
        1.capitalize() 首字母变大写       2.endswith/startswith()  是否x结束/开始
        3.find() 检测是否在字符串中       4.isalnum() 判断是否是字母和数字
        5.isalpha() 判断是否是字母        6.isdigit()  判断是否是数字
        7.islower()  判断是否是小写        8.join()  循环取出所有值用xx去连接
        9.lower/upper  大小写转换          10.swapcase   大写变小写,小写变大写
        11.istrip/rstrip/strip 移除左/右/两侧空格   12.split()  以某种自定义的方法切割字符串
        13.title()  把每个单词的首字母变成大写     14.replace(old,new,count=None)  old被换字符串,new替换字符串,count换多少个。无count表示全部替换
        15.count()  统计出现的次数
'''
test = 'python'
print('第一个字符:%s,第二个字符:%s'%(test[0],test[1]))   # ***没有%c,都是%s
print('首字母变成大写:%s'%test.capitalize())     # 注意函数的使用方法******
dataStr = 'I love Python'
print(dataStr.find('o'))   # 会返回该字符第一个该字母的下标,后面有都不管了,如果没有找到返回-1  ***注意find里面有引号!

# 切片:
str_q = 'hello world'
print(str_q[2:5])   # 2-5下标之间的数据
print(str_q[2:])    # 第三个字符到最后

'''
列表list:有序的数据集合
特点:
    1.支持增删改查
    2.列表中的数据是可以变化的【数据项可以变化,内存不会改变】
    3.用[] 来表示列表类型,数据之间可以用逗号来分割,注意:数据项可以是任何类型的数据
    4.支持索引和切片的操作     索引:表示可以用下标
    
常用的方法:
 ***1.append 在列表后面追加元素出现的次数       2.count  统计元素出现的次数
    3.extend 扩展,相当于批量添加               4.index  获取指定元素索引号 [下标]
    5.insert  在指定位置插入                 ***6.pop   删除最后一个元素,也可以移除指定的一项,参数是索引值
    ***7.remove  移除左边找到的第一个元素[指定的],参数是元素         8.reverse  反转列表
    9.sort  列表排序   reverse = Ture  倒序    10.del  删除
'''

# 列表:
# li = []  # 空列表
# li = [1,2,3,'你好']
# print(len(li))  # len()函数是返回字符串的长度或者是元素的个数
# listA = ['abcd',25,12.32,'wangzha',True]   # abcd 为一个元素
# print(listA[0])
# print(listA[1:3])
# print(listA*2)  # *****表示整体复制了2次
# listA.append(['ffff','vvv'])
# listA.append(222)
# listA.extend([11.15,'99'])
# print(listA)
# listA[0] = 'python'    # -------修改---------
# print(listA)
# del listA[0]           # -------删除---------
# del listA[1:3]          # ---------批量删除-----

# listA.index(99,20,25)     # ---------从下标20开始查,查到下标25处-------------

'''
元组:是一种不可变的序列,在创建以后不能做任何修改,只能读
    1.不可变
    2.用()创建元组类型,数据项用逗号来分割
    3.可以是任何的类型
    4.当元组中只有一个元组时,要加上逗号,不然解释器会当做整型来处理
    5.支持切片操作
'''
# 元组:  ----------------和列表相似-------------
tupleA = () # 空元组
tupleA = ('abcd',98,99.99,[11,15,'wzha'])
print(tupleA[::-1])    # -------------步长为负时,反向---------------
tupleA[3].remove(15)   # ---------元组不能改,但是元组里面的列表元素可以改-----------
print(tupleA)
tupleA[3][0] = 27134   # **************这样的表示方法**************
tupleB = (1)            # 默认为整型
tupleB = (1,)           # 此时为元组类型
print(type(tupleB))


'''
字典:是由 键值对 组合的集合,通常使用键来访问数据,效率非常高,和list一样,支持对数据的添加,删除,修改
特点:
    1. 不是序列类型,没有下标的概念,是一个无序的 键值集合,是内置的高阶数据类型
    2. 用{}来表示字典对象,每一个键值对用逗号分隔
    3. 键 必须是不可变的类型,值可以是任意类型
    4. 每个键必定是唯一的,如果存在重复的键,后者会覆盖前者
'''
# 字典键的添加:
dictA = {}  # 空字典
dictA['name'] = '菜鸡甜'   # ---------name是key,菜鸡甜是value----------
dictA['age'] = 21
dictB = {"pro":'计算机','school':'贵州大学'}  # ----------字典的初始化-----------
print(dictA)
print(dictB['school'])      # ----------字典的引用-----------
dictB['school'] = '中国大学'  # ----- 修改--------
dictB.update({'pos':'软件工程'}) # -----更新---------也可以添加------
print(dictB.keys())          # -----------获取所有的键----------
print(dictB.values())         # -----------获取所有的值----------
print(dictB.items())         # -----------获取所有的键和值----------
for key,value in dictB.items():    # ***********注意:key就是键,value是值**********
    print('%s==%s'%(key,value))
    pass
del dictA['age']            # ----------删除---------
dictB.pop('pos')            # --------也是删除--------
dictA.update({'目标':'成都电子科技大学'})
dictA.update({'love':'Q'})
print(dictA)
#  ***************字典的排序**************
sorted(dictA.items(),key=lambda d:d[0]) # 按照key排序
sorted(dictA.items(),key=lambda d:d[1])  # 按照value排序


# ————————————————————-公用方法----------------------
'''
1. 合并操作 +   :两个对象相加操作,会合并两个对象  【字符串,元组,列表】
2. 复制  *      :对象按指定次数进行 + 操作       【字符串,列表,元组】
3. 判断元素是否存在 in     :判断指定元素是否存在于对象中    【字符串,列表,元组,字典】
'''
strA = '人生苦短'
strB = '我用java和python'
print(strA + strB)
print((strA + strB) * 2)

#  ----------------函数-----------------
'''
定义:
def 函数名():
    函数体【一系列的python语句】
    pass
**************函数的参数****************
1.实际参数
2.默认参数:
def sum1(a=10,b=20):   #在调用时,可以不带实参,则参数就是10和20,也可以带实参,如: sum1(12),此时a为12,b不变
    print(a+b)
    pass
3.不定长参数(可选参数):当参数的个数不确定时使用,比较灵活    ********************************************
def sum2(*ags):
4.关键字可变函数(关键字可选参数): **来定义,在函数体内 参数关键字是一个@@@字典类型@@@@  key必须是一个字符串
    def sum3(**kewargs):
    
    可选参数:接受的数据是元组类型
    关键字可选参数:接收的数据是字典类型
    
——————————*和**参数可以混合使用------------
def complexFunc(*args,**kwargs)   ******注意:可选参数必须放到关键字可选参数之前
def complexFunc(**kwargs,*args)      这样是错误的!!!!!!!!!!!!!!!!!

# # #  #  # # : 函数返回值:
    函数内部有return时,有返回值,如果没有则返回None
    类型:可以返回任何类型
    和c一样,函数执行到return后就结束
'''
# *******************函数的备注信息***********************
'''
def 函数名(函数的参数):
    ''‘
    这个函数是用来打印个人信息的!
     :return:             #  ***********注意****************
    ''’
*****************全局变量和局部变量***************
在函数内部,局部变量的优先级更高!
如果在函数内部要想对全局变量进行修改的话,必须使用global 关键字进行声明 

小结:
    1.在python中   万物皆对象,在函数调用的时候,实参传递的就是对对象的引用
    2.把控在函数内部的处理是否会影响到函数外部的数据变化
    3.参数传递是通过对象引用来完成的   参数传递是通过对象引用来完成的    参数传递是通过对象引用来完成的 


# ----------------------匿名函数-------------------------
关键字: lambda 
lambda 参数1,参数2,参数3:表达式
    text = lambda x,y : x + y     # 计算两个数的和
***匿名函数冒号后面的表达式有且只有一个,注意:是表达式,不是语句   缺点缺点缺点缺点缺点
***匿名函数自带return

M = lambda x,y : x+y    
M(23,19)     # 通过变量去调用匿名函数

# ----可以替换传统双分支的写法----
语句a if 条件b else 语句c   # b成立时表现为a,否则表现为c
age = 25
print('可以参军' if age>18 else '继续上学')  

testFun = lambda x,y : x if x>y else y
print(testFun(5,6))

# --------------------递归函数----------------
注意:设置结束条件
    eg:求n的阶乘:

'''
def funCe(n):
    result = 1
    for item in range(1,n+1):  #左开右闭
        result *= item
        pass
    return result
    pass

def diguiFinc(n):
    '''
    求阶乘函数
    :param n: 阶乘参数
    :return: 
    '''
    if n == 1:
        return  1
    else:
        return  n*diguiFinc(n-1)

print('------------递归函数------------')
print(funCe(5))
print('5的阶乘:{}'.format(diguiFinc(5)))

def getComputer(*args):   # 不定长参数
    result = 0    # 注意:要在函数里面申请变量,在外面命名变量会报错
    for item in args:
        result += item
        pass
    print('result=%d'%result)
    pass
getComputer(1)
getComputer(1,2)
getComputer(1,2,3)

def KeyFun(**kewargs):
    print(kewargs)
    pass
dictC = {'name':'钱','age':20}
KeyFun(**dictC)            # 以字典类型做实参,注意:**符号
KeyFun(name='钱',age=21)   # 以键值对的做参数的传递

def calComputer(num):
    li = []
    result = 0
    i = 1
    while i <= num:
        result += i
        i += 1
        pass
    li.append(result)
    return  li
print(calComputer(5))

# 写一个函数,接收n个数字,求这些参数数字的和
# 写一个函数,找出传入的列表或元组的奇数位对应的元素,并返回一个新的列表
# 写一个函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新的内容返回给调用者。PS:字典中的value只能是字符串或列表
def sumFinc(*args):
    '''
    这个函数是所有数字的和!
    :return:
    '''
    result = 0
    for item in args:
        result += item
        pass
    return result
answer = sumFinc(1,2,3)
print('answer={}'.format(answer))         # 如果是输入n个整数如何输入???????????????????????

def processFinc(con):
    listD = []
    i = 1
    for item in con:
        if i%2 == 1:
            listD.append(item)
            pass
        i += 1
        pass
    return listD
listD = [1,3,6,'Abc','love',21.3]
result = processFinc(listD)
print(result)

def processDictFinc(dicParms):
    '''
    处理字典类型的函数
    :param dicParms: 字典
    :return: value长度不超过2的内容
    '''
    dicNew = {}
    for key,value in dicParms.items():
        if len(value) > 2:
            dicNew[key] = value[:2]    # 左闭右开!!!!!!!!!!!
            pass
        else:
            dicNew[key] = value
            pass
        pass
    return dicNew
    pass
dictObj={
    'name':'菜鸡甜',
    'age':'20',       # 注意:如果这里20为整型,那么函数中的len()会报错,因为他是整型撒!!!
    '专业':'云计算',
    'school':'贵州大学',
    'hobby':['唱歌','跳舞','rap','篮球']
}
print(processDictFinc(dictObj))

# ---------------------------------------内置函数------------------------------------------------------
'''
# ---------------数学运算
1.abs() 取绝对值                    2.round(x,y)   返回浮点数x的近似值,保留y位小数
3.pow(x,y) 返回x的y次方              4.divmod(x,y)  返回一个包含商和余数的元组(a // b, a % b)
5.max(x,y,z,....) 返回参数的最大值,参数可以为序列       6.sum()   对系列进行求和计算,参数可以为可迭代对象
7.eval() 执行字符串表达式,并返回表达式的值  
语法:eval(expression[,globals[,locals]]) 返回表达式计算的结果*************
参数:expression - 表达式     
    globals - 变量作用域,如果被提供,则必须是一个字典类型对象
    locals  -- 变量作用域,局部命名空间,如果被提供,可是是如何映射对象

print(max([23,12,5,6,9,78,100,345]))
a,b,c = 1,3,5
eval('a+b+c')  # 动态执行,等于6
eval('a+b+c',{'a':3,'b':5,'c':6})  # 可以对变量赋值,但是只能用字典类型
eval('sumF()')  # 里面甚至可以是一个函数

# -----------------类型转换函数
新的类型(需要转换的)  int(),str()
1.bin() 将10进制转换为二进制                 2.hex()   将10进制装换为16进制
3.list=()  元组转换为列表                    4.tuple=()   列表转换为元组
5.dict()  可以创建字典,也可以转换为字典类型*************
6.bytes() 返回一个新字节数组,这个数组里的元素是可变的,并且每个元素的值得范围:0<=x<256

# -----------------序列操作函数
1.all() 判断可迭代参数iterable中的所有元素是否都为true,是返回true,否则false    0,空,FALSE 外都是TRUE   ***类似逻辑运算符的and
2.any() 判断给定的可迭代参数iterable是否全部为False,否返回False,如果有一个True,则返回True     ***类似逻辑运算符的or
3.sorted(iterable[,cmp[,key[,reverse]]]) 
对可迭代对象进行排序,reverse--排序规则, reverse = True 降序, reverse = False 升序
4.range()  生成整数列表,步长默认为1
5.zip()  将对象中的对应的元素打包成一个个元组,然后返回由这些元组组成的列表
  会把序列中的对应的索引位置的元素存储为一个元组,如果长度不一样,就以最少的打包,多的那部分舍弃
6.enumerate()  用于将一个可遍历的数据对象(如列表,元组或者字符串)组合为一个索引序列(加一个索引)
     同时列出数据对象和数据下标,一般用于for循环中

**********sort 和 sorted 的区别********** 
1.sort是应用在list上的方法,而sorted是对所有可迭代对象的排序操作
2.list 的sort是对已有的list进行排序操作,返回的是原本的list,而sorted是返回一个新的list

----------------------------------set集合-----------------------------------------------------------
集合:一个无序且不重复的元素集合     
set 不支持索引和切片,是一个无序且不重复的容器,类似于字典,但是没有key,只有value     通常会那它去重
创建方式:
    1.set1 = {"1","2"}
    2.list = ['1','2','3']
       set2 = set(list)

1.add()  添加操作                                       2.clear()  清空操作
3. a.difference(b) = a - b  两个集合的差集,a中存在,b中不存在         4. a.intersection() = a & b  取交集,a中存在,b中也存在
5. a.union(b) = a|b  都是并集,都是放在a中                             
6. a.pop 集合a随机移除某个元素并且获取那个参数,就是从集合中那数据并且同时删除
7. a.discard()    指定移除元素                8. a.update(b)    更新集合
'''
tup = (1,2,3)
li = list(tup)
dic=dict(a=1,b='hello',c=[1,2,3])
print(dic)
print(bytes('我喜欢python',encoding = 'utf-8'))
li = [1,5,8,7]
li.sort()
print(li)
# li.append('a')
print(li)
li = sorted(li,reverse=True)
print(li)
'''
def loobsInfo():      # --------------------------------------数据的多组输入-------------------------
    ’‘’
    存储图书信息!
    :return:
    ’’‘
    books = []   # 存储所有图书的信息:有编号、书名、位置
    print('---------以空格分割-----------\n')
    bookId = input('请输入编号:\n')
    bookName = input('请输入书名:\n')
    bookPos = input('请输入位置:\n')
    idlist = bookId.split(' ')      # ----------------数据的多组输入-----------
    namelist = bookName.split(' ')  # ----------------数据的多组输入-----------
    poslist = bookPos.split(' ')    # ----------------数据的多组输入-----------
    booklist = zip(idlist,namelist,poslist)
    for bookitem in booklist:
        dictBooks = {'编号':bookitem[0],'书名':bookitem[1],'位置':bookitem[2]}
        books.append(dictBooks)
        pass
    for item in books:
        # print('编号:{}  书名:{}  位置:{}'.format(item[0],item[1],item[2]))
        print(item)
        pass
    pass
loobsInfo()
# 刘贵盈吃屎第一部 刘贵盈吃屎第二部 刘贵盈吃屎第三部 刘贵盈吃屎第四部
# 520 521 522 523
'''
# enumerate()的使用
listObj = ['a','b','c','f']
for index,item in enumerate(listObj):
    print(item)
    print(index,item)
    pass

# 刘贵盈吃屎第一部 刘贵盈吃屎第二部 刘贵盈吃屎第三部 刘贵盈吃屎第四部
# 520 521 522 523

# 求三组连续自然数的和:求出1到10,、20到30和35到45的三个和
# 100个和尚吃100个馒头,大和尚一个人吃3个馒头,小和尚3个人吃一个馒头。请问大小和尚个多少人?
# 指定一个列表,列表里含有唯一一个只出现一次的数字。写程序找出这个“独一无二”数字

def sumRange(m,n):
    '''
    求从m到n的整数的和
    :param m:
    :param n:
    :return:
    '''
    return  sum(range(m,n+1))
    pass
def computerNumber(m,x):
    '''
    计算大小和尚各多少(大和尚一个吃三个,小和尚三个吃一个)
    :param m: 大小和尚的数目
    :param x: 馒头的数目
    :return:
    '''
    temp = 3*m - x
    return temp // 8 * 3
    pass
def findUniqueNumber(li):
    li.sort()
    i = 0
    while True:
        if li[i]==None or li[i+1]==None:   # 好像有问题!!!!!!
            print('Error!')
            break
            pass
        elif li[i] == li[i+1]:
            i += 2
            continue
            pass
        else:
            print(li[i])
            break
            pass
        pass
    pass
# li = input('请输入一个列表:(以空格分隔)')
# listF = li.split(' ')
# findUniqueNumber(listF)

# ------------------------------------------面向对象--------------------------------------------------
'''
面向对象:将函数和数据绑定在一起        ====怎么做?====
    按人们认识客观世界的系统思维方式,采用基于对象(实体)的概念建立模型,模拟客观世界分析、设计、实现软件的办法
面向过程:根据业务逻辑去写代码         =====谁来做?====

-----------------类和对象:

类:  //类是具有一组 相同或者相似属性和行为的一系列对象的集合!类是对象的抽象化 
    类的名称:类名
    类的属性:一组数据
    类的方法:行为
对象:是一个实实在在的东西,类的实例化,具象化

-----------------定义类和对象:
1.类定义: //大驼峰命名
class 类名:
    属性     【类属性和实例属性】
    方法    【实例方法】

eg:
class Person:
    name = '菜鸡甜'    # 类属性
    age = 21
    def eat(self,food):    # 这是一个实例方法,在类里面定义的方法,可以传参
        print('干饭人!')
        pass
    def run(self):   # 第一个参数默认是self,可以是其他的名字,但是这个位置必须被占用
        print('跑得飞快')
        pass
    def __init__(self):  # 定义在方法里面的属性,实例属性,通过参数self去定义的【【【【魔术方法】】】】
        self.zhuanye = '软件工程'    # 实例属性
        pass
    pass

2.对象:
格式:  对象名 = 类名()  
qtt = Person()     # 注意:这里要打()
qtt.name
qtt.eat()  # 调用方法
qtt.colour = 'red'     # 添加类属性
 
 __init__  魔术方法,----------------可以传参----------
1.python 自带的内置函数 具有特殊的函数  使用双下划线包起来的【魔术方法】
2.是一个初始化的方法  用来定义实例属性和初始化数据的,在创建对象的时候自动调用   不用动手去调用
3.利用传参的机制可以让我们定义功能更加强大的 类

qtt = Person('菜鸡甜','男','21') 

-------------重要----重要------重要------------self---------------------
特点:
1.所谓的self,可以理解为对象自己,某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,
   所以开发者只需要传递后面的参数即可。
2.self的名字可以更改的  只是约定成俗的定义成了self 
3.self指的是 类实例对象本身,相当于java中的 this
class Person:
    def __init__(self,name,sex,age):   # **************
        self.name = name                # *************
        self.sex = sex                  # *************
        sel.age = age
        pass
    def __new__(cls, *args, **kwargs):
        ''’
        创建对象实例的方法  每调用一次  就会生成一个新的对象  cls是class的缩写
        :param args:
        :param kwargs:
        ''‘
        return object.__new__(cls)
        pass
    pass
qtt = Person()
--------------魔术方法---不需要手动调用-------------
1.__init__   初始化一个类,在创建实例对象为其赋值时使用
2.__str__    在将对象转化为字符串 str(对象) 测试的时候,打印对象信息   通常用于查看对象信息
3.__new__     创建并返回一个实例对象,调用了一次,就会得到一个对象。
4.__class__   获得已知对象的类(对象 __class__)
5.__del__    对象在程序运行结束后进行对象销毁的时候调用这个方法来释放资源

------------------------------析构方法-----------
__del__方法  释放资源的
删除或销毁对象,
在对象里面声明这个方法,可以手动删除对象      def dog  删除dog这个对象
重要的应用就是来操作    对象的释放  一旦释放完毕  对象变不能再使用

-----------------------------继承----------
在python中展现面向对象的三大特征: 封装、继承、多态
1.  封装:指的是把内容封装到某一个地方,便于后面的引用   eg:类的属性,方法
2.  继承:指可以继承父类的内容【属性和行为】,也就是说爸爸有的儿子都有,儿子有的爸爸不一定有
    对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需要继承父类而不比一一是每个方法
    在定义一个类的时候,在类名后面加一个括号,里面是类的名字/继承父类
class dog(Person):    类dog继承了父类PersonD的方法 ///单继承,只有继承了一个爹
class dog(Person,Cat)    多继承,继承多个父类的方法,
    ***注意***:当多个父类存在相同方法的时候,优先级:自己 > 第一个父类 > 第二个父类 ......按顺序  
    父亲的方法可以一级一级的传递到子类
重写:就是方法覆盖,并不会更改父类里面的方法
    在子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中的方法
----------------------在子类的方法中调用父类的的方法
class Dog(name,age):
    def __init__(self):
        self.name = name
        self.color = red
        pass
    pass
class keji(Dog):
    def __init__(self,name,color):
        Dog.__init__(self,name,color)   # 手动调用父类的方法,因为除了和父类有相同的属性,
        self.age =  heighr = 90         # 也有父类中没有的
        super().__init__(name,color)     # super 是自动找到父类,进而调用方法  自动调用,可有多个父类的方法
        pass
    pass   
    
----------------------------多态-----------
1.定义:定义时的类型和运行时的类型不一样,此时就成为了多态 [同一种行为对于不同的子类【对象】有不同的行为表现]
实现的前提:(1)继承:多态必须发生在父类与子类之间
          (2)重写:子类重写了父类
增加程序的灵活性和扩展性    ========鸭子类型===========不关注对象类型本身,而是关注他的行为,只要他对象的行为像一个鸭子,即使他是鸟,我们也可以说他是鸭子         

-----------------类属性和实例属性
1.类属性可以被类对象和实例对象共同访问使用的, 类属性只能由实例对象所访问  
2.所有实例对象的类对象指针指向同一类对象。实例属性在每个实例中独有一份,而类属性是所有实例对象共有一份
3.类属性只能通过类对象进行修改

---------------------类方法和静态方法
1.类方法 用 @classmethod(修饰器) 来进行修饰,参数默认是cls
通过他来传递类的属性和方法,不能传递实例的属性和方法
class Student:
    name = 'qtt'
    @classmethod
    def get_name(cls):
        return cls.name   # 访问类属性
        pass
    @classmethod
    def change_name(cls,data):
        cls.country = data   #修改类属性
        pass
2.静态方法:
类对象的静态方法,需要用@staticmethod来表示静态方法,静态方法不需要如何参数
静态方法主要是存放逻辑性代码,逻辑上属于类,但是和类、实例对象没有交互,他不会涉及到类中的属性和方法操作
注意:一般情况想,我们不会通过实例对象去访问静态方法
 
类方法的第一个参数是类对象cls  进而去引用类对象的属性和方法
实例方法的第一个参数必须是self, 通过这个self可以去引用类属性或者类方法,实例属性的优先级高于类属性

----------------------------------私有化属性和方法------两个下划线-----------
语法:两个下划线开头,声明改属性为私有,不能再类的外部被使用或直接访问。
使用场景:
    1.把一个特定的一个属性隐藏起来  不让类的外部进行直接调用,在类的内部可以访问和修改
    2.我想保护这个属性  不想让属性的值随意的改变
    3.保护这个属性,不想让派生类【子类】去继承

私有化方法:内部调用,子类不能继承,外部不能调用
    1._xxx:前面加一个下划线,表示的是protected类型的变量,即保护类型只能允许其本身与子类进行访问。
    2.__xxx__: 魔法方法,一般是python自有,开发者不要创建这类型的方法
    3.xxx_:避免属性名与python关键字冲突
-------------------实现对私有属性的访问和修改
1.可以写两个方法,一个去访问,一个去修改  【要写在类里面,因为只有在类里面才能调用私有属性】
2.定义一个类属性Property属性,通过直接访问属性的形式去访问私有属性 
eg:
class PersonTo:
    def __init__(self):
        self.__age = 18
        pass
    def get_age(self):  # 访问
        return self.__age
    def set_age(self,age): # 修改
        if age < 0:
            print('年龄不能小于0')
        else:
            self.__age = age
            pass
        pass
    age = property(get_age,set_age)   # 必须是以get,set开头的方法名才能被调用 
3.装饰器,在方法上使用装饰器
    访问是 @property  添加属性标志 提供一个getter方法
    修改是 @xxx.setattr   提供一个setter方法
    
------------------------------__new__方法-------------
***********new方法在init方法前面执行
xiaom = PersonTo()  # 实例化的过程会自动调用 new  去创建实例
在新式类中, __new__ 才是真正的实例化方法,为类提供外壳制造框架,然后调用改框架内的构造方法__init__进行丰满操作
只有继承了object,才能用这个方法
class Person1:
    def __init__(self,name,age):
        self.__name = name
        self.__age = age
        pass
    def get_name(self,name):
        self.__name = name
        pass
    def get_age(self,age):
        if age>=0 and age<=120:
            self.__age = age
        else:
            print('Error!')
        pass
    def getage(self):
        return self.__age
    def __str__(self):
        return '{}的年龄是{}岁!'.format(self.__name,self.__age)
-----------------------------单例模式  
是一种常用的软件设计模式
    要求:确保某一个类只有一个实例对象,并且提供一个全局的访问点
步骤:利用类属性保存初次创建的实例对象,第二次实例化的时候判断类属性是否有保存实例对象
    如果有就返回类属性保存的,如果没有就调用父类__new__方法创建新的实例对象
eg:日志的logger的操作,网址计数器,Windows资源管理器,系统回收站,【只有一个,确保不会出错】

------------重要---重要----重要-----重要-----------------------------错误和异常处理-----------------------------------------------------------
1.什么是异常:程序在执行中发生的错误。
语法格式:【处理异常】
try:
    可能出现错误的代码块
except:
    出错之后执行的代码块  捕获到的错误才会在这里执行
excep:
    .......
else:
    当try中没有错误时,才执行这里面的代码块
finally:
    不管有木有出错都执行的代码块

1.对于except 在捕获错误异常的时候 只有根据具体的错误类型来捕获的
2.用一个块 可以捕获多个不同的异常,python内置大概31种错误类型
3.assert 关键字:*****************
    当Expression部分为True时,则正确执行,程序继续下去;当判断为False时,则抛出后面的e错误提示
    assert Expression,e   
------------------------异常处理技巧------
抛出的异常应该说明原因,有时候你知道异常类型也猜不出所以然的
只处理你知道的异常,避免捕获所有异常然后吞掉它们
不要使用异常来控制流程,那样你的程序会无比难懂和难维护
如果有需要,切记使用finally来释放资源

try:
    print(b)
    li = [1,2,3]
    print(li[10])
    pass
except NameError as msg:
    print(msg)
    pass
except  IndexError as msg:
    print(msg)
    pass
except  Exception as result:   # 可以捕获所有类型  ¥¥¥¥¥¥¥
    print(result)
    pass
    
注意:不需要在每个可能出错的地方去捕获,只要在合适的层次去捕捉错误就可以了 这样的话 就大大减少我们写try---except的麻烦
eg:
def A(s):
    return  s**2
def B(s):
    return s - 21
def main():
    try:
        B('0')
        pass
    except Exception as msg:
        处理.....
        print(msg)
        pass
    pass
----------异常的抛出机制:
    如果运行时发生异常 解释器会查找相应的异常捕获类型,如果在当前函数里面没有找到的话,它会将异常传递
    给上面的调用函数,看能否处理,如果在最外层没有找到的话,解释器就会退出,程序就down了
    
-----------------------------------自定义异常
自定义异常,都要直接或间接继承Error或Exception类
由开发者主动抛出自定义异常,在python中使用raise关键字

-------------------------------------动态绑定类属性和方法
1.为实例对象添加属性:
    qtt.weight = 120      qtt是实例对象,weight是属于这个对象的,类里面没有
2.动态添加类属性:
    Student.school = '家里蹲大学'   Student 是类
3.动态添加方法:
实例对象绑定:
需要用到typs库: import types  导入库
    cat.run = types.MethodType(funC,cat)   将方法funC给对象cat的run【原本cat里面没有run方法】 ,赋给对象cat 
绑定类方法:------
Student.newMethod = classText   # 就像直接赋值一样 将classText 绑定给类Student

-------------------------------------__slots__属性
1.限制要添加的实例属性,还可以节约内存空间
class Student2(object):
    __slots__ = ('name','school','score')     # 限制实例属性的添加,只能创建在这里面的属性,否则失败
    pass
2.在继承关系中的使用:
  子类未声明__slots__时,那么是不会继承父类的__slots__,此时子类是可以随意进行属性的赋值的
  子类声明了__slots__时,继承父类的__slots__,此时子类__slots__的范围是其自身 + 父类的__slots__。

'''
'''
class ToolongMyException(Exception):
    def __init__(self,len):
        self.len = len
        pass
    def __str__(self):
        return '您输入的姓名长度是' + str(len(self.len)) + '超过长度了.....'
    pass

def name_text():
    name = input('请输入您的名字:')
    try:
        if len(name) > 5:
            raise ToolongMyException(name)
        else:
            print(name)
            pass
        pass
    except ToolongMyException as result:
        print(result)
        pass
    finally:
        print("It's ok!" )
name_text()

'''   # 自定义异常处理

'''
class Animal:
    def say_whate(self):
        print('我会动物叫...')
        pass
    pass
class Dog(Animal):
    def say_whate(self):
        print('我会嘎嘎叫...')
        pass
    pass
class Cat(Animal):
    def say_whate(self):
        print('我会喵喵叫...')
        pass
    pass

def commonInvoke(obj):   # 统一调用
    obj.say_whate()
    pass

listObj = [Dog(),Cat()]   # 列表里面也可以装对象
for item in listObj:
    commonInvoke(item)
    pass
Am = Animal()
Am.say_whate()  # 不变·
'''       # 多态

# ***************************************实例决战紫禁之巅-----------------------------------
'''
决战紫禁之巅有两个人物,西门吹雪和叶孤城
    *属性:
        name  玩家的名字
        blood 玩家血量
    *方法:
        tong() 捅了对方一刀,对方掉血10滴
        kanren() 砍了对方一刀,对方掉血15滴
        chiyao()  吃一颗药,补血10滴
        __str__ 打印玩家状态

class Role:
    def __init__(self,name,blood):
        self.name = name
        self.blood = blood
        pass
    def tong(self,enemy):
        enemy.blood -= 10
        info = '【%s】捅了【%s】一刀'%(self.name,enemy.name)
        print(info)
        pass
    def kanren(self,enemy):
        enemy.blood -= 15
        info = '【%s】砍了【%s】一刀' % (self.name, enemy.name)
        print(info)
        pass
    def chiyao(self):
        self.blood += 10
        info = '【%s】吃了一颗药,回复了10滴血 '%(self.name)
        print(info)
        pass
    def bishaji(self,enemy):
        enemy.blood = 0
        info = '【%s】 对 【%s】 发动了必杀技!'%(self.name,enemy.name)
        print(info)
        pass
    def __str__(self):
        return  '【%s】还剩下%s滴血'%(self.name,self.blood)
        print(info)
        pass
    pass


xmcx = Role('西门吹雪',100)
ygc = Role('叶孤城',100)
while True:
    number1 = int(input('请输入数字:(1.西门吹雪捅了叶孤城一刀    2.西门吹雪砍了叶孤城一刀  3.西门吹雪喝了一瓶药  4.必杀技)\n'))
    number2 = int(input('请输入数字:(1.叶孤城捅了西门吹雪一刀    2.叶孤城砍了西门吹雪一刀  3.叶孤城喝了一瓶药  4.必杀技)\n'))
    if number1 == 1:
        xmcx.tong(ygc)
        print(ygc)
        pass
    elif number1 == 2:
        xmcx.kanren(ygc)
        print(ygc)
        pass
    elif number1 == 4:
        xmcx.bishaji(ygc)
        print(ygc)
        pass
    else:
        xmcx.chiyao()
        print(xmcx)
        pass
    if number2 == 1:
        ygc.tong(xmcx)
        print(xmcx)
        pass
    elif number2 == 2:
        ygc.kanren(xmcx)
        print(xmcx)
        pass
    elif number2 == 4:
        ygc.bishaji(xmcx)
        print(xmcx)
        pass
    else:
        ygc.chiyao()
        print(ygc)
        pass
    if ygc.blood <= 0:
        print('【%s】 死了,游戏结束!'%(ygc.name))
        break
        pass
    if xmcx.blood <= 0:
        print('【%s】 死了,游戏结束!'%(xmcx.name))
        break
        pass
    pass
'''
# class A:
#     name = 'qtt'
#     def eat(self):
#         # print('a')
#         return self.name
#         pass
#     def change_name(self,name):
#         self.name = name
#         pass
# class B:
#     def eat(self):
#         print('b')
#         pass
# class C(A,B):
#     pass
# print('---------------')
# a = C()
# print(a.eat())
# a.change_name('qdd')
# print(a.name)
#
#
# qtt=Person1('qtt',20)
# print(qtt)
# qtt.get_age(18)
# print(qtt.getage())

# =================================================文件操作与模块==================================
'''
# -------------------------------------文件操作:
1.打开文件(写):   找不到文件就创建一个new
    open('文件名称','打开模式')  打开模式:r,w....  可以选择二进制打开:wb,....【就是在原有的模式后加一个‘b’】
    w:会覆盖掉以前的, 而a则会在文件已有内容后面添加
fobj = open('./text.text','w')
fobj.write('苍茫的天涯是你的爱!')
fobj.close()  要关闭了!!!!!释放句柄

读数据操作:
f = open('text.text','r')
f.read(x)   x省略读所有数据, 否则读读x字节  
f.readline() 读一行    f.readlines() 读所以行,返回一个列表【行为单位】

使用 read() 读取的文件内容,得到的是 str 格式的,
用 write() 方法写入的时候也需要是 str 格式
编码检测工具——chardet:
    chardet是一个Python包,提供测试文本的编码方法,最后返回的是对编码方法的一个估计

*****利用pyth内置的csv模块读取数据:
csv:逗号分隔符文件的读取
csv.writer() 作为写入器
writerow() 方法逐行写入
import csv
f = open('text.text','r')
reader = csv.reader(f) # 用csv.reader()方法生成reader对象 
    遍历csv文件的行,从csv文件中读取的每一行都作为字符串列表返回 !!!!!!!!!!!!!!!!!!!!!!!!!
content = []
for con in reader:
    content.append(con)

cont = ['@','25','type','qtt']
writer = csv.writer(f)
for con in cont:  # 逐个内容写入
    writer.writerow(con)
f.close()

with 关键字:上下文管理对象:
优点: 自动释放打开的关联对象    ->取代.close()

小结:
文件读写的操作方式:
read , r, rb+ , r+
只读:r, r+
适用于文件、图片、视频、音频这样的文件读取:rb   rb+
write w w+  wb+  wb  a ab  
每次都会创建文件:w , wb+  w+  !!!!!
在原有的文件的基础之后去【文件指针的末尾】追加,不会每次去创建new文件:a  ab  a+

2.文件的备份:
def copyFile():
    old_file = input('请用户输入要备份的文件名:')
    fileList = old_file.split('.')
    new_file = fileList[0] + '_备份.' + fileList[1]
    old_f = open(old_file,'r')
    new_f = open(new_file, 'w')
    content = old_f.read()
    new_f.write(content)
    old_f.close()
    new_f.close()
    pass
    
如果当文件过大时,一次性读取是不可取的,内存着不住!!
def copyBigFile():
    old_file = input('请用户输入要备份的文件名:')
    if not old_file:
        print('[ERROR]:请输入正确的文件路径')
        old_file = input()
        pass
    fileList = old_file.split('.')
    new_file = fileList[0] + '_备份.' + fileList[1]
    try:
        with open(old_file,'r') as old_f, open(new_file,'w') as new_f: # with 真好用!!!!
            while True:
                content = old_f.read(1024)  # 一般都是读1024字节
                new_f = new_f.write(content)
                if len(content) < 1024:
                    break
    except Exception as msg:
        print(msg)
    pass
copyBigFile()


3.---文件定位:
指的是当前文件指针读取到的位置,光标位置。在读写文件的过程中,如果想知道当前的位置,可以使用tell()来获取
tell() 返回指针当前所在的位置
     对于中文来说,每个汉字占用两个字符,一字符一位
with open('text.text','r') as f:
    print(f.read(3))
    print(f.tell())
    print(f.read(2))
    print(f.tell())

truncate(x) 可以对源文件进行截取x位操作,从光标开始!

seek(offset,from) 在操作文件的过程中,可以定位到其他位置,就是控制光标所在位置
   offset:偏移量单位字节,负数是往回偏移
   from位置:0表示文件开头,1表示当前位置,2表示文件末尾
with open('text.text','rb') as f:    # 注意这里用'r'不行   两字符,一个汉字
    date = f.read(2)
    print(date.decode('gbk'))
    f.seek(-2,1)
    print(date.decode('gbk'))
    pass
# 对于用'r'模式打开文件。 在文本文件中,如果没有使用二进制的选项打开文件,
# 只允许从文件的开头计算相对位置,从文件尾部计算或者当前计算的话,就会引发异常

----------------------------------------------模块:
*模块的介绍:
1.模块就是封装了一堆函数的py文件,就像是一个工具包,要使用里面的工具,得先将工具包拿过来。模块也是一样,
在程序中需要使用的模块得先将模块导入!
2.调用模块得方法,格式:模块名.函数名    这样调用可以防止不同模块中有同名的方法导致错误!!!
import 到首次导入模块文件的时候  会发生如下3步操作:
    打开模块文件
    执行模块对应的文件,将执行过程中产生的名字都丢到模块的名称空间
    在程序中会有一个模块的名称指向模块的名称空间去
form ... import .. :可以选择导入多个或者一个函数【部分导入】
    在使用函数的时候,可以不加模块名字,而是直接使用函数;
from time import * 导入所有函数   == import time
模块的搜索路径:3种
给模块去别名as:
    import time as myTime    ***别名
    取别名后,不能用原来的模块取名字要用别名
    
***************OS模块操作文件:
    对文件进行重命名、删除等一些操作,在python中可以利用os模块。
    os模块提供一些系统级别的操作命令
常用的方法:
import os
os.rename('1.py','666.py')
    1.修改文件名:rename(需要修改的文件名,新的文件名)
    2.删除文件:remove(待删除的文件名)
    3.创建文件夹:mkdir(文件夹名称)
    4.删除文件夹:rmdir(文件夹名称)
    5.获取当前目录:getcwd()
    6.切换目录 :chdir(路径)
    7.路径拼接:os.path.join(path1[,path2[,...]])   将多个路径组合后放回
          path = os.path.join(os.getcwd(),'gl')
          
*******************模块的制作
1.模块的定义:
    在python中,一个.py文件就是一个模块
2.模块的作用:
    可以使我们有逻辑的去组织我们的python代码
    以库的形式去封装功能,非常方便的去让调用者去使用
    可以定义函数 类 变量 也可以包含可执行的代码
    注意:!!!不同的模块可以定义相同的变量名,但是每个模块中的变量名作用域只是在本模块中
3.模块的分类:
    内置模块   自定义模块   第三方模块
# import module
# from module import add
from  module import *
x = 5
y = 3
print(add(x,y))

********如何让模块里面的某些代码不执行********:
    在模块中用:
    if __name__ == '__name__':
        不希望被其他文件使用,或者是被其他文件导入时不执行的代码块!!!
        pass  
__all__魔术变量的作用是:如果在一个文件中存在__all__变量,那么意味着这个变量中
的元素会被from xxx impot *时会被导入,对于import方式来讲  无所谓 有木有 都可以全部的引用 
    
*********模块的发布:可以让其他开发者引用
1.将写好的包放到一个xxxx/目录下
2.在这个目录想创建一个文件setup.py文件
在文件2里面写入下面的代码:
from distutils.core import setup
# name 模块名称
# version 版本号
# description 描述
# author 作者
# py_modules  要发布的内容
setup(name = 'my_module',version='1.0',description = 'my module',
author = 'qtt', py_module = 'test1.A', 'text1.B','test2.A','text2.B',)
3.创建模块:
    python setup.py build  # 在终端输入这个命令
4.生成压缩包:
    python setup.py sdist   # 在终端输入这个命令
可以把压缩包发给别人安装了

**********模块的安装:
1.将压缩包解法:
    tar -zxvf my_module-1.0.tar.gz
2.进入my_module-1.0文件夹
3.执行命令安装python setup.py install
4.查看是否安装成功

**********缺失值处理:
1.如果缺失值占比很小,可以删除掉样本
2.可以使用均值对缺失值进行填充

利用pandas导入数据
1.利用pandas将数据存入一个DataFrame数据结构中
2.使用pandas内置的mean()和fillna()方法进行缺失值填充
3.使用pandas内置的hist()方法画出缺失值填补后的图
4.用matplotlib画分布图   结合pandas和numpy进行绘图
    绘制分布图有利于观察出异常情况


----------------------------------编码和解码----------------------------
1.编码:encode   解码:decode
2.str 通过解码函数 decode() 转换为 unicode , unicode 通过编码函数 encode() 转换为 str 
3.GBK 和 Unicode
    unicode 字符串是在 ‘ ’ 或 “ ” 前加 u 来赋值的,同时访问一个元素则是一个字符
    encode() 函数和 decode() 函数可以设置参数,指定编码方式

---------------------------------------------------正则表达式--------------------------------
一概念:
    又称规则表达式,通常被用来检索、替换那些符合某个模式(规则)的文本

1.python中的re模块,使python语言拥有全部的正则表达式功能,re模块由C语言编写,速度快!!
2.常用的匹配规则--匹配字符--操作符:
    . 表示任何单个字符         
    [  ] 字符集,对单个字符给出取值范围, [abc]表示a、b、c, [a-z]表示a到z单个字符
    [^  ]非字符集,对单个字符给出排除范围,[^abc]表示非a或b或c的单个字符
    * 前一个字符0次或无限次扩展 ,abc*表示ab,abc,abcc,abccc等
    + 前一个字符1次或无限次扩展, abc+表示abc, abcc, abccc等等
    ? 前一个字符0次或1次扩展, abc?表示ab , abc
    | 左右表达式任意一个
    {m} 扩展一个字符m次, ab{2}c 表示abbc
    {m,n} 扩展前一个字符m置n次   ab{1,2}c 表示abc, abbc
    ^ 匹配字符串开头, ^abc 表示abc且在一个字符串的开头
    $ 匹配字符串结尾,  abc$表示abc且在一个字符串结尾
    ( ) 分组标记,内部只能使用 | 操作符,  (abc) 表示abc; (abc|def)表示abc、def
    \d 数字,等价于[0-9]
    \w 单词字符,等价于[0-9a-zA-Z],意思是匹配所以字母(英文字母)和数字
补:!!!!!!
[^ \t\v\n\f\r] 匹配所有非空白字符(非空格/制表符/换行符)
[^...] 中的 ^ 表示求补,这种模式匹配所有未在括号里列出的字符 
    如果需要在字符组里包括 ^,就不能放在第一个位置,以免混淆含义。
    可以写\^恢复其本来含义;如 果需要在字符组包括 - ],也必须写 \- 或 \]
    
3.如果一个正则表达式串只包含常规字符,它就只能与自己匹配。也就是说,常规字符串是最基本的正则表达式。
    r1 = re.compile('abc’) ,则r1这个正则表达式实际上只能匹配普通字符串'abc',和普通字符串并没有什么不同。

4.为了方便,re 用换意串形式定义了几个常用字符组:
    \d:与十进制数字匹配,等价于 [0-9]
    \D:与非十进制数字的所有字符匹配,等价于 [^0-9]
    \s:与所有空白字符匹配,等价于 [ \t\v\n\f\r]
    \S:与所有非空白字符匹配,等价于 [^ \t\v\n\f\r]
    \w:与所有字母数字字符匹配,等价于 [0-9a-zA-Z]
    \W:与所有非字母数字字符匹配,等价于 [^0-9a-zA-Z]
5.圆点字符.可以匹配任意一个字符
eg: a..b 匹配所以以a开头b结束的四字字符串

6.重复重复重复重复: *  +
eg:
    任意大的正整数:[1-9][0-9]* 或者 [1-9]\d* 
    'a+' 等价于 'aa*'
    整数(表示整数的字符串)的一种简单模式 '-?\d+',其前面的'-?'部分表示可以以负号开头。 
    描述北京常规的固话号码:'(010-)?[2-9][0-9]{7}'表示可选010前缀,2-9开头,后面的任意数字加起来一共可以有七位。
    重复范围中的 m 和 n 均可以省略,α{,n} 表示 α{0,n},而 α{m,} 表示 α{m,infinity}。
    α{n} 等价于 α{n,n},α? 等价于 α{0,1} α* 等价于 α{0,infinity},α+ 等价于 α{1,infinity} 
!:所以涉及重复额地方都会涉及一个概念--->贪婪模式
    一般程序设计语言中,大多会默认正则表达式进行贪婪匹配,即可以匹配的多个互相有包含关系的时候,
    只匹配最大的那一个

7.首尾匹配:只与一行匹配,且只匹配首尾!!!!
行首匹配:以 ^ 符号开头的模式,:
    '^for'只能匹配以'for'为前缀的一行。如果将其与一行'books for children'匹配,将得到 None
行尾匹配:以 $ 符号结尾的模式,只与一行的后缀匹配
    'fish$'只匹配以'fish'为后缀的一行。如果将其与一行'cats like to eat fishes'匹配,将得到 None
很多语言中^$都分别代表行首/行尾的标记。例如文本编辑器VIM
*******^与$代表的一行的开头与结束,而不是整个字符串的开头与结束。
        如果一个字符串中出现了多个换行符号,则模式或许可能与多个行首、行尾形成匹配。******
相同相似:
    串首匹配:\A 开头的模式只与被匹配串的前缀匹配
    串尾匹配:\Z 结束的模式只与被匹配串的后缀匹配

8.匹配IP地址的正则表达式:
补:IP地址的格式:
    a.b.c.d的形式【点分十进制】,a,b,c,d都是0~255之间的十进制整数,实际上是32位二进制。
IP地址精确写法:
    0-99 : [1-9]?\d
    100-199   :  1\d{2}
    200-249  :  2[0-4]\d
    250-255:  25[0-5]
注意:!!!!不能直接表示200-255!!!
所以匹配IP地址:
    (([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5]).){3}([1-9]?\d|1\d{2}|2[0-4]\d|25[0-5])
    为什么不是直接重复4次,因为有'.',注意整体关系

eg:
P(y|yt|yth|ytho)?n     ’Pn’、’Pytn’、’Pythn’、’Python’
Python+                 ’Python’、’Pythonn’、’Pythonnn’……
Py[th]on                ’Pyton’、’Pyhon’
Py[^th]?on              ’Pyon’、’Pyaon’……      【不能出现】’Pyton’、’Pyhon’……
Py{:3}n                 ’Pn’、’Pyn’、’Pyyn’、’Pyyyn’……
[\u4e00-\u9fa5]         匹配中文字符

*******:
刚才我们介绍的正则表达式是独立于语言存在的。'正则表达式'不是基于哪一种编程语言的概念,而是一个字符串语言本身的概念。在各种语言中都有不同的实现方式
在Python中,有一个内置模块re,是专门用于处理正则表达式的模块
刚才我们介绍的有关|与*的应用是正则表达式的通用语法。
在Python中使用正则表达式时,包括但不限于这些简单的语法。我们有更多更加简单的方法可以写出通配符等我们需要的模式。
----------------------------------------------re模块!!!!
1.re.match方法:     起始位置 起始位置起始位置起始位置起始位置起始位置
re.match 尝试从字符串的起始位置匹配一个规则,匹配成功就返回一个match对象,
    否则返回None。可以使用group()获取匹配成功的字符串。
语法:re.match(pattern,string,flags=0)
    patter:匹配的正则表达式
    string:要匹配的字符串
    flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。
# import re
# str = 'pfsfpfsfdsjkoj a '
# res = re.match('p',str)  # 返回match对象
# print(res.group())
# print(type(res))

2.原生字符串(raw string),是python里一种写字符串的形式!
    用法:在字符串前面加r或者R前缀,eg: R'abcdefg'
    注意:原始字符串里‘写出什么就是什么“。即 \ 不作为转义符,在相应 str 对象里原样保留。
        eg:R’C:\courses\python\progs' 的等价写法:---->’C:\\courses\\python\\progs’ 

3.re 规定了一组特殊字符,称为元字符,它们在匹配字符串时起着特殊的作用:
    14个: . ^ $ * + ? \ | { } [ ] ( )
    这些在普通字符串中只有少量的\的转义字符代表特殊内容
    而在正则表达式中,这些都代表特殊内容!!!      
****意思是:同样的字符串在不同环境下,代表不同含义!!!
    与一般字符串类似,\在正则表达式中也是转义字符
    在\后面的普通字符将获得特殊含义。如果只是单纯的想表示'\',让他不具备特殊含义,就在他前面加一个'\'
    eg:print('\courses\1python\2progs') 会出现乱码,因为1和2会被赋予特殊含义!!
    所以正确的应该是:print('\\courses\\1python\\2progs')

3.pattern类:
python正则表达式包re中,最基本的雷就是pattern
正则表达式的对象可以从普通字符串生成语句为:
    r1 = re.complie(普通字符)
    意思是:内容不变,但是他已不再是一个普通的字符串,而是一个有梦想的正则表达式了!!强

4.两种写法:
    *re.search(pattern,字符串)   # 直接把普通字符串pattern当正则表达式语使用
    
    *r1=re.compile(pattern)   # 先用pattern生成正则表达式对象r1
     r1.search(字符串)
     第一种简单,但是如果我们要使用这个正则表达式多次,那么第二种就更好!!

5.re模块中的函数:
    *MatchObject对象:它存储了匹配位置,匹配内容等信息;
    ***re模块的函数都是贪婪模式:
        贪婪匹配的含义不是要找出'最多'的匹配,而是要在每一次匹配的时候找到'最大'的匹配。
        这提醒我们,一定要当心使用*,最好都改为由限定范围的{:n}

    *search: 
        1.语法:re.search(pattern,字符串)
        2.返回一个MatchObject对象
        3.注意:它只是寻找从左到右第一个与正则表达匹配,而不是找所有匹配位置。
    *findall:
        1.findall函数可以找出所有匹配,并把它们从左到右作为一个列表返回。如果无匹配,返回空列表。
        2.re.findall(pattern,字符串)
    *finditer:
        1.与findall基本一样,只是finditer返回的是一个迭代器。
        2.当数据大时,选择这个比较好
    *match:
        1.用法:re.match(pattern,字符串),和search类似。
        2.唯一不同的是re.match()只从头开始匹配,re.search()可以匹配任一位置的字符串。
    *fullmatch:
        1.和match类似,但是它不但是“从头匹配”,而是“从头到尾”全部匹配。
        2.fullmatch就是用来检测pattern与整个string是不是匹配的
    *split:
        1.用法:re.split(pattern,string):将string中所有与pattern匹配的东西做为分割符,继而将字符串分割为一张表。
        2.re.split(pattern,string,maxsplit),maxsplit参数,规定最多划分几次,到了次数,后面的就不在划分。
    *sub:
        1.re.sub(pattern,repl,字符串),将字符串与pattern匹配成功的内容替换为repl
        2.re.sub(pattern,repl,字符串,count = 一个整数),count参数限定了最大匹配替换次数。
        3.re.sub(pattern,function,string),function是一个函数,可以把所有匹配的对象全部替换为作用function后的对象
    *subn:
        与sub的使用方法基本一样,不同的是,subn返回的对象是一个被替换后的字符串与替换次数的两元组:

6.正则表达式的应用:
    *去掉标点符号:可以选择将标点符号替换为空格---> ' '
        注意:中文的标点符号大多是没有歧义的。而英文的标点符号大多数本来就是正则表达式中有特殊含义的符号。
        所以,必须在前面运用转义字符'\'才能将特殊含义转换为其原来的含义。
        即:punctuation_e = "[\s+\.\!\/_,$%^*(+\"\']+"   
        然后使用re.sub函数既可以将标点符号替换为空字符' ' 
    *用分词工具分词之后的语句中,仍然有很多分错的情况。对于分错的解决方法有两种,
        第一种是将分错的词作为词典加入分词工具的词典中再重新分词;
        第二种是用正则表达式将这个词提取出来进行替换。第一种方法其实更常用一些,但是有时候可能仅仅需要暂时替换查看效果,
        那么所有句子都重新分词的成本看起来就比较大了。所以第二种方法也是需要掌握的。

eg:定义一个函数,求字符串中出现的所有整数之和
def sumInt(fname):
    re_int='\\b(0+|[0-9]\d*)\\b'  # 注意:\b表示不匹配任何实际字符【英文字母,数字】,意思是匹配到的(..)两边不能是实际字符,否则匹配不成功
    inf = open(fname)
    if inf == None:
        return 0
    ilist = map(int,re.findall(re_int,inf_read()))  # 注意map()的用法,两种!!
    s = 0
    for n in ilist:
        s += n
    return s

****map():返回的是新的列表,原来的列表不会改变!
    1.格式转换:map(int,(1,3,2)) 
    2.map(function,iter), iter里面的每个元素都执行一遍functi函数,添加到新的列表中,最后返回一个列表!
    
7.使用正则表达式抽取数据:
   抽取每个课程的课程状态
import re
import io

html_data = io.open('hackdata.html','r',encoding = 'utf8')
for line in html_data:
    target = pattern.search(line)
    if target:
        all_content = target.group(0)
        content = target.group(1)
        print (all_content + '     '  + content)
**********补:
    1.io模块的open()有encoding参数,所以用它
    2.search()函数会搜索整个 line字符串,寻找匹配的字串,并返回match类型对象。
      group(n)返回第n个捕获组获取的字符,如果n=0,则返回匹配的整个字符串
    3.上面的pattern为:
            re.compiler(r'(.+?)')
            字符 . 负责匹配除了换行字符意外的任何字符,字符 +? 负责字符匹配的范围
            
8.使用BeautifulSoup模块抽取数据:
    1.BeautifulSoup将网页转换成一个复杂的树形结构, 每个节点都是一个Python对象。
      首先,我们创建一个`BeautifulSoup`对象`soup`,通过`soup.head`,可以获取``中的数据内容。
    2. 网页是具有树形结构的数据,每个标签都是树形结构的一个节点,定位节点,找到与节点相关的数据
eg:*获取网页源码中的数据
import io
from bs4 import BeautifulSoup
html_data = io.open('hackdata.html','r',encoding = 'utf8')
soup = BeautifulSoup(html_data)
print soup.head

****调用 findAll() 函数,去定位标签

,抽取所有与之相关的数据:
alllines = soup.findall('p')
for line in allline:
    content = line.content[0]
    parint(content)

9.HTML解析器:
    *ElementTree是标准库的一部分
    *BeautifulSoup是一个流行的第三方库
    *lxml是一个功能齐全基于c的快速解析库
    
----------------练习:
# 1.尝试提取某网站书籍名称、作者、出版社、价格信息?


-------日期数据的处理--->datetime模块:
1.主要包括三个类:
    Time:主要包括一天内的小时、分钟、秒、毫秒信息
    data:包含年、月、日
    datetime:是前两者的结合。   注意:这个是datetime模块中的datetime类!!!!!!

------datetime:
1.datetime.strptime():  
    *用法:datetime.strptime(date_string,format)
    *date_string:日期字符串   
    *format:日期字符串的日期格式
        eg: %y 两位数的年份表示,区间为[00, 99]      
             %Y 四位数的年份表示,区间为[000, 9999]
             %m 月份 [01-12]
             %d 月内中的一天 [0-31]
             %H 24小时制小时数 [0-23]
             %I 12小时制小时数 [01-12]
             %M 分钟数 [00=59]
             %S 秒 [00-59]
             %a 本地简化星期名称
             %A 本地完整星期名称v
             %b 本地简化的月份名称
             %B 本地完整的月份名称
             %c 本地相应的日期表示和时间表示
             %j 年内的一天 [001-366]
             %p 本地A.M.或P.M.的等价符
             %U 一年中的星期数 [00-53]星期天为星期的开始
             %w 星期 [0-6],星期天为星期的开始
             %W 一年中的星期数 [00-53]星期一为星期的开始
             %x 本地相应的日期表示
             %X 本地相应的时间表示
             %Z 当前时区的名称
             %% %号本身
        *datetime对象可以直接进行减法,但是不能进行加法,因为加法没有意义,时间相加有个鬼意义!!
        *isweekday():可以直接查看这个日期对象是星期几。 注意weekday()和其的区别!
        *fromordinal():接受一个整型的天数,返回一个天数所等价的年数、月数、日数的date对象!
        *now():可以获得现在的时间   ---> dt = datetime.datetime.now()


-----------------------------------------------numpy基础---------------------------
1.numpy概念:专门用于矩阵化运算、科学计算的开源Python
2.基本数据结构:ndarray
    np_ar = numpy.array([[1,2,3],[4,5,6]])  --->二维数组
    *作为ndarray对象里的数据有时并不是所需要的,那么可以使用ndarray对象的astype() 方法转为指定的数据类型
    *ndarray和array的区别:
        1.ndarray是对象,er而array是numpy中的函数
        2.ndarray是由array这个方法来创建的一个对象
    *丢失的数据类型主要有None 和 np.nan
        np.nan是一个float类型的数据 None是一个NoneType类型

2.ndarray对象的相关操作:
    *索引!!!***
        *切片操作:和对列'表list的切片索引相似,不过变为了多维!
            eg:np_ar[m:n:step1,x:y:step2]  --->二维
                表示:[m,n)行中[x,y)列     step1 = step2 = 1时,步长可以省略!!
               :np_ar[(a,b,c),(x,y,z)] : 取二维数组中(a,x),(b,y),(c,z)三个值!
            *索引后还可以直接对应该位置重新赋值!
            *可以通过shape属性得到数组的行数和列数!
        *布尔值索引:通过添加条件判断数组中每一个值的 真/假 转为布尔值在 对原数组进行进行索引,为真True会被取出来:
                np_ar[np>=2]   //直接将布尔值的数组对原数组进行索引,True的部分被保留,其实执行了两步
    
    *切分:使用split将ndarray按照行平均分为几个ndarray
        np.split(sh_ndarray,2) //没两行作为一个新的array
        也可以按照下标位置进行划分:
            np.split(sh_ndarray,[1,-1])  //将第一行、最后一行以及剩下的行分为三个新的array
        
    *重构:reshape 方法将所有元素按照指定行指定列进行重构
        sh_ndarray.reshape((2,8))    //将16个元素按照2行8列的方式进行重构
        
    *拼接:将多个
        *通过 vstack 沿纵轴拼接
        *通过 hstack 沿横轴拼接
        *通过 concatenate 进行拼接   //首尾拼接
            eg:c = np.concatenate(sh_ndarray[0],sh_ndarray[0]))
    
    *转置: transpose 方法、在数组后加 .T
    
    *翻转: fliplr 左右翻转、flipud 上下翻转
    
    *对位运算:指 ndarray 进行加减乘除运算时,使对应位置的数值进行加减乘除运算,
       !!!当两个 ndarray 的维度不一致时,则没有对齐的维度上会分别执行对位运算,这种机制叫做广播(broadcasting)

    *结构化数据:联想c里面的结构体,可以存放许多不同的数据:
        *numpy.dtype(object,align,copy)
             object - 要转换为的数据类型对象
             align - 如果为 true,填充字段使其类似 C 的结构体。
             copy - 复制 dtype 对象 ,如果为 false,则是对内置数据类型对象的引用
        *eg: 
            student = np.dtype([('name','S20'), ('age', 'i1'), ('marks', 'f4')]) 
            a = np.array([('abc', 21, 50),('xyz', 18, 75)], dtype = student) 
            *S20->string,20byte   i1->int8   f->float32       //1*8  4*8
            object -> 'O' :python对象!!比如date!!!!!
            *一般都是元组元组元组元组元组元组元组!!!!
        
        *按命名索引:
            sh_np['date'][:5]  # sh_np['date'] 指抽取命名为'date'的那一列的前五个元素
            a[name][:1]  和上面的例子相关联!
        
3.内置操作函数:
    *数学函数:
        *numpy.log()函数是numpy模块提供的生成自然对数函数
            eg:a = np.array([1,2,3,4])   np.log(a) --> 0   0.6931  1.098612 1.362943 
    
    *运算函数:
        在计算的时候,会遇到差分、累加的情况
        *numpy.diff() 计算差分:
            语法:numpy.diff(a,n,axis)  沿着指定轴计算第N维的离散差值
                a:输入矩阵
                n:可选,代表要执行几次差值,默认是1次
                axis:默认是最后一个,按哪一个轴进行差值计算    axis = 1 -->按列相减;   axis-->0 按行相减;   高位向地位相减!!
            eg:a = numpy.array[1,3,4,5,8]    numpy.diff(a,n=1,axis=-1) ---> [2,1,1,3]
        
    *统计函数:
        numpy提供了很多计算最大值、最小值、均值、中位数等统计量的函数,比如统计最大值的函数numpy.amax()
        *numpy.amax(a,axis,out,keepdims):  还有很多函数!
            a: numpy.adarray数据类型
            axis: 指定统计最大值的轴  ,可以设置为None
            out: 输出格式,需要和输出的维度、元素个数相同 ,可以设置为None
            keepdims: 是否保留原输入数据的维度,默认为False

4.线性代数模块linalg: 它在numpy模块中的!!!!
    *线性代数模块 linalg 常用于向量及矩阵的基本运算以及特征值分解、SVD分解等矩阵分解过程
    
5.随机模块random:numpy中的
    *概念:
        伪随机数的产生,可从离散分布和连续分布中产生
        在蒙特卡洛方法、随机积分、随机过程模拟等很多方面都有应用
        指定随机种子(seed)产生相同的随机数序列
        eg: random.seed(666)  
            random.rand(2,3)  产生一个2行3列的矩阵,其中的每一个元素为[0,1]之间的浮点数随机数
            random.randint(0,10) 产生一个[0,10]之间的整型随机数!
        补:`random`支持的离散分布包括二项分布、几何分布、超几何分布等,还支持常用的均匀分布、正态分布、指数分布、logistic、伽马分布、泊松分布等连续分布。
        对于random.seed():
                random.seed() 会改变随机生成器的种子;传入的数值用于指定随机数生成时所用算法开始时所选定的整数值,
                如果使用相同的seed()值,则每次生成的随机数都相同;如果不设置这个值,则系统会根据时间来自己选择这个值,
                此时每次生成的随机数会因时间的差异而有所不同。
    
    *常见分布的产生方式:
        random.binomial(n=5,p=0.5,size=5)  二项分布:产生5个服从二项分布B(5,0.5)的样本  详细理解:https://blog.csdn.net/u014571489/article/details/102942933
        random.uniform(-1,1,5)    均匀分布:产生5个服从均匀分布U[-1,1]的样本
        random.normal(size=(2,3))  标准正态分布:产生2*5的标准正态分布样本
    
--------练习:产生 B(10,0.5) B(5,0.5) B(1,0.5) 二项分布图
        (分别从二项分布B(10,0.5)、B(5,0.5)、B(1,0.5)中产生10000个样本存入数组)  
import numpy as np
from numpy import random
import matplotlib.pyplot as plt
# %matplotlib inline   具体作用是当你调用matplotlib.pyplot的绘图函数plot()进行绘图的时候,或者生成一个figure画布的时候,可以直接在你的python console里面生成图像。
# 生成了一个带坐标轴的figure对象,并且画布颜色是白色的。

fig = plt.figure(facecolor='white')
ax = fig.add_subplot(111)
random.seed(666)

date_10 = random.binomial(n=10,p=0.5,size=10000)
date_5 = random.binomial(n=5,p=0.5,size = 10000)
date_1 = random.binomial(n=1,p=0.5,size = 10000)

# 画图部分:
data = [date_1,date_5,date_10]
n_list = [1,5,10]
color = ['b','r','c']
fig,ax = plt.subplots()
for row,c,n in zip(data,color,n_list):
    ax.hist(
        row,
        color = c,
        label= '$B($' + str(n)+',0.5' + '$)$'
    )
ax.legend(loc = 'upper right', fontsize = 10)
plt.axis('tight')
plt.grid('off')
plt.show()
     
--------------------------------------------------Pandas数据分析-------------------------------------------------
*what is DataFrame?
    DataFrame是一个以命名列方式组织的分布式数据集。
    在概念上,它跟关系型数据库中的一张表或者1个Python(或者R)中的data frame一样,但是比他们更优化。
*numpy, scipy, pandas:
    *NumPy是Python科学计算基础包:
    *SciPy是一组专门解决科学计算中各种标准问题域的包的集合,跟NumPy的有机结合完全可以替代MATLAB的计算功能
      eg:scipy.integrate:数值积分和微分方程求解器
        scipy.linalg:扩展了由numpy.linalg提供的线性代数和矩阵分解功能
        scipy.optimize:函数优化器以及根查找算法
        scipy.special:SPECFUN(实现了许多常用数学函数如伽玛函数的Fortran库)的包装器
        scipy.stats:标准概率分布、各种统计检验方法以及更好的描述统计法
        scipy.weave:利用内联C++代码加速数组计算的工具
    *Pandas:
        pandas提供了使我们能够快速便捷地处理结构化数据的大量数据结构和函数
        pandas兼具NumPy高性能的数组计算功能以及电子表格和关系型数据库灵活的数据处理功能
        pandas提供了大量适合于金融数据的高性能时间序列功能和工具

--------------------数据文件操作:
1.读入数据:
    *pandas提供了一些用于将表格型数据读取为DataFrame对象的函数,常用的函数为read_csv和read_table
    
    *其函数的选项可以划分为几大类:
        -索引:将一个或多个列当做返回的DataFrame处理,以及是否从文件、用户获取列名
        -类型推断和数据转换:包括用户定义值的转换、缺失值标记列表等
        -日期解析:包括组合功能,比如将分散在多个列中的日期时间信息组合起来
        -迭代:支持对大文件进行逐块迭代
        -不规整数据问题:跳过一些行、页脚、注释或其他一些不重要的东西
        
    *read_csv和read_table。read_csv 从文件、URL、文件型对象中加载带分隔符的数据:
        -默认分隔符为逗号。
        -read_table从文件、URL、文件型对象中加载带分隔符的数据。默认分隔符为制表符(“\t”)
    
    *read_csv/read_table常用参数介绍:
        -path:表示文件系统位置、URL、文件型对象的字符串
        -sep/delimiter:用于对行中个字段进行拆分的字符序列或正则表达式
        -header:用做列名的行号。默认为0(第一行),若无header行,设为None
        -names:用于结果的列名列表,结合header=None 
        -skiprows: 需要忽略的行数  ,在处理不规则文件时,skiprows可以帮助跳过文件中的若干行
            +df = pd.read_csv(path, skiprows=[0,2,4])
            
        -na_values:一组用于替换NA的值
            +一般用于处理缺失值的,na_values可以接受一组表示缺失值的字符串,用字典将列的特定值指定为NaN。    
            +map_id = {'sex':['Female','size':[3]}  将列名为sex的列中填Female处改为Nan
            +tips = pd.read_csv('tips.csv', na_vaules=map_id)
            
        -nrows:需要读取的行数(从文件开始处算起)
            +在处理较大文件时,there is tow choise for you:
                    .通过nrows指定读取的行
                    .通过设置chunksize,逐块读取。和csv.reader(f)类似,就是将一次读取一行变为可以设置的n行,不是只读取一次
                        eg:chunker = pd.read_csv('xxx.csv', chunksize = 50)
                        
        -verbose:打印各种解析器信息,比如“非数值列中缺失值的数量”
        -encoding:用于unicode的文本格式编码。例如,“utf-8”表示用UTF-8 编码的文本
        
2.写出数据:
    *to_csv写出数据到文件夹,默认会写出行和列的标签,可以设置index和header选项进行选择!
        df = pd.read_csv('iris.csv')
        df.to_csv('out.csv')
        !type out.csv

3.变量离散化:
    *为了便于分析,连续数据常常被离散化或拆分为“bin”。要实现该功能,需要使用pandas的cut函数。
        pandas返回的是一个特殊的Categorical对象,可以将其看做一组表示“bin”名称的字符串。实际上,
        它含有一个表示不同分类名称的levels数组以及一个为要划分特征数据进行标号的labels属性:
       
4.缺失值填补:
    *NaN-->Not a number, 表示浮点数和非浮点数组中的缺失值数据,它只是一个便于被检测出来的标记而已:
        python内置的None值也会被当做NaN处理
    
    *对于DaraFrame对象,dropna默认丢弃任何含有缺失值的行,how=‘all’只丢弃全为NA的那些行,axis=1指定丢弃列
        -可以选择丢弃数据中全部为缺失值的行,
        -选择丢弃数据中全部为缺失值的列
    *fillna方法可以填充缺失数据,并且可以增加不同的选项
        -直接使用该方法进填充:
            df.fillna(0).head()
        -使用字典方式填充:
            df.fillna({'gender'':'M', 'friend':0}).head()
        -使用method方式填充,method=‘ffill’或‘bfill’(前向或后向填充),limit可以调节最大填充数量
            +ffill:向前填充的意思是:对于缺失行,用该行的前一行填充该行,前一行仍然存在
            +同理bfill

5.数据标准化:
将数据按比例缩放,使之落入一个小的特定区间,一般目的在于:去除数据的单位限制,转化为无量纲的纯数值,
便于不同单位或量级的指标能够进行比较和加权。数据的归一化便是一个典型的案例。
    *数据归一化:
        -把数转换为(0,1)之间的小数,把有量纲的表达式转换为无量纲的表达式
    
    5.1 Min-Max标准化: 
        Min-Max标准化是指对原始数据进行线性变换,将值映射到[0,1]之间
        -对序列:X1, X2, ..., Xn进行变换:
            Yi = ( Xi - min{X1, X2, ..., Xn} ) / (max{X1, X2, ..., Xn}  -  min{X1, X2, ..., Xn} )
            则新序列Y1, Y2, Y3,..., Yn属于[0,1]且无量纲。
            
    5.2 Z-Score标准化:
        *基于原始数据的均值(mean)和标准差(standard deviation)来进行数据的标准化。
         其主要目的是将不同量级的数据统一化为同一个量级,统一用计算出的Z-Score值衡量,保证了数据间具有可比性。
        -对序列:X1, X2, ..., Xn进行变换:
            Yi = ( Xi - x ) /  s         --> x:均值,  s:方差
    
    5.3 均值归一法:
         u是表示均值,value表示在一组数据中第i个元素的值:
             x = ( value - u ) / max
        或者:
            x = ( value - u ) / ( max - min )
    
    5.4 还有指数转化、 向量归一化、 小数定标(Decimal scaling)标准化等

**Pandas中并没有提供直接进行数据标准化的方式,可以使用scikit-learn中preprocessing的方法进行数据的标准化操作。
通常用两种标准化处理方式: Min-Max标准化和Z-Score标准化:
    Min-Max -->将数据转换为区间[0,1]中的值
    Z-Score -->将不同量级的数据统一化为同一个量级

----preprocessing模块:
    -它提供了StandardScaler工具类,包含名为Transformer的API,可以在训练集上计算均值和标准差,并且能够在之后将同样的转换应用于测试集。
        scaler = preprocessing.StandardScaler().fit(df)
        scaler.transform([[-1.,  1., 0.,4.,3.]])    --->应用于新数据
    -它提供了MinMaxScalar方法对数据进行[0,1]标准化:
        min_max_scaler = preprocessing.MinMaxScaler()
        scaler = min_max_scaler.fit_transform(df)

6.数据合并:DataFrame合并 ---> 数据库风格,和数据库的连接类似!!!!
    数据集的合并或连接运算通过一个或多个键将行连接起来,pandas中主要使用merge函数
    -默认的情况下,merge会将重叠的列名当做键,可以显示地用left_on 和 right_on指定; 连接的时候产生的是行的笛卡尔积
    
    -left_on 和 right_on :
        既然是和数据库的连接相同,那么这里的left_on和right_on相当于等值连接的两个表中用以连接的两个列,
            eg:Student.Sno = Course.Sno 
    
    -默认的情况下,merge做的是'inner'连接
        inner --> 也就是如果我left_on和right_on列中,其中一个有,一个没有的,抛弃掉不连接
        outer -->  两个表中的数据都要,不会存在丢弃,left_on里面有,但是right_on里面没有的,用NaN填充!!!
        left  -->  应该算是outer 的一半,right_on有的,left_on没有的丢弃
        right -->  同理left
    
    -索引上的合并:
        有时候,DataFrame中的连接键位于其索引上,此时可以传入left_index=True或right_index=True(或两个都传)以说明索引应该被用作连接键
    
    -轴向连接:
        使用concat函数可以将不同的Series或DataFrame进行轴向连接;传入axis=1可以在列上进行轴向连接  
        
7.数据组合:
    -对数据集进行分组并对各组应用一个函数,这是数据分析过程中的一个重要环节。在数据集准备好之后,通常的任务就是计算分组统计或生成透视表。 
    
    -Pandas提供了一个灵活高效的 groupby 功能,它使你能以一种自然的方式对数据集进行切片、切块、摘要等操作。
        这和数据库的分组 groupby 相似 ----> 就是对数据分组并对各组应用一个函数!!!
    
    -pandas中的对象可以在行(axis = 0) 或列 (axis = 1)上进行分组,然后将一个函数应用(apply)到个分组并产生一个新值。
        最后所有这些函数的执行结果会被合并(combine)到最终结果对象中!!
    eg:
        df = pandas.read_cvs('xxx.cvs') 
        
        #按照sex进行分组:
        grouped = df['tip'].groupby(df['sex'])
        
        # 计算平均值:    
        grouped.mean()
        
    -一次传入多个数组,通过两个键对进行分组,得到的Series具有一个层次化索引
    -利用agg()使用自定义聚合函数,一次传入多个聚合函数。

            
-----------------------------------------matplotlib模块-------------------------------------------
https://blog.csdn.net/qq_34859482/article/details/80617391?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161930964816780255239353%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=161930964816780255239353&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-80617391.first_rank_v2_pc_rank_v29&utm_term=matplotlib

注意:在这里:
    left-->左   right-->右   bottom-->下   top-->上

import matplotlib.pyplot as plt
1.认识Matplotlib:
    1.1认识Figure:
        Figure对象,就像一张画板,我们需要它才能作画!
            eg:fig = plt.figure()
    
    1.2 Axes:
        在拥有Figure对象之后,在作画前我们还需要轴,没有轴的话就没有绘图基准,
            所以需要添加Axes。也可以理解成为真正可以作画的纸。
            eg:
                import matplotlib.pyplot as plt
                fig = plt.figure()
                ax = fig.add_subplot(221)  # 前两个参数确定将整个画板划分为几块【2*2】,最后一个表示第几个Axes,取值范围:[1,2*2];
                ax.set(xlim=[0.5,5.5],ylim=[0,10],title = 'An Example Axes',
                       ylabel = 'Y-Axis', xlabel = 'x_Axis'
                       )        lim-->范围    label-->标签,名称  
                plt.show()

    1.3 Multiple Axes:
        通常用于循环画图:
        eg:
            fig, axes = plt.subplots(nrows=2,ncols=2)  nrows-->行数  ncols-->列数
            axes[0,0].set(title='Upper Left')
            axes[0,1].set(title='Upper Right')
            axes[1,0].set(title='Upper Left')
            axes[1,1].set(title='Upper Right')
        补:
            fig, axes = plt.subplots(1,2,1) 等同于:
                # fig = plt.figure()
                # ax = fig.add_subplot(1,2,1)
    
    1.4 Axes Vs .pyplot:
        .pyplot -->更简单易懂,适用于快速绘图,简单图
        Axes --->通常用于处理复杂的绘图工作,能力更强。
        eg:
            plt.plot([1, 2, 3, 4], [10, 20, 25, 30], color='lightblue', linewidth=3)
            plt.xlim(0.5, 4.5)
            补:[1,2,3,4]--->x的取值   [10,20,25,30]--->y的取值   两个列表大小应该相同
        
2.基本绘图2D:
    2.1 线:
        plot()函数画出一系列的点,并且用线将他们连接起来:
        eg:     
            x = np.linspace(0,np.pi)
            y_sin = np.sin(x)
            y_cos = np.cos(x)
            ax1.plot(x, y_sin)
            ax2.plot(x, y_sin, 'go--', linewidth=2)
            ax3.plot(x, y_cos, color='red', marker='+', linestyle='dashed')
            
        补:matplotlib.pyplot.plot()参数详解:
        网址:https://blog.csdn.net/qq_31192383/category_6665721.html
            1.一般调用形式:
                plot([x],y,[fmt],data=None,**kwargs)   单线条
                plot([x], y, [fmt], [x2], y, [fmt], ....data=None,**kwargs) 多条线一起画
                *[fmt]-->是一个字符串来定义图的基本属性,如:颜色(color)、点型(marker)、线型(linestyle)
                    具体形式--> fmt = '[color][marker][line]'  ->>接收的是每个属性的缩写!
                如果属性用全名则不能用 fmt 参数来组合赋值,应该用关键字:
                    eg:plot(x,y2,color='green', marker='o', linestyle='dashed', linewidth=1, markersize=6)
            2.格式:
                matplotlib.pyplot.plot(*args, scalex=True, scaley=True, data=None, **kwargs)
                参数含义:
                    *args - 要绘制图形的函数横、纵坐标向量;
                    scalex、scaley - 是否要进行横纵坐标轴的缩放,默认进行缩放,如果不进行缩放则在绘制的图形中1:1显示横纵坐标轴;
                    data - 可通过data提供绘图数据;
                    **kwargs - 图形属性,信息的可选属性可参考帮助文档,下面介绍几种常用的属性:
                        color:颜色
                        linestyle:线条样式
                        linewidth:线宽
                        marker:数据点样式-->常见样式有'.'(点)、'o'(圆点)、'v'(下三角)、'+'.....
                        markeredgecolor:数据点边界颜色
                        markeredgewidth:数据点边界宽度
                        markerfacecolor:数据点填充颜色
                        markersize:数据点大小
                        label:标签
        *通过关键字参数的方式绘图:
        eg: 注意:data的用法!!!!!!!
            x = np.linspace(0, 10, 200)
            fig, ax = plt.subplots()
            data_object={
                'x': x,
                'y1': 2 * x + 1,
                'y2': 3 * x + 1.2,
                'mean': 0.5 * x * np.cos(2*x) + 2.5 * x + 1.1}
            # 填充两条线之间的颜色:
            ax.fill_between('x', 'y1', 'y2', color='yellow', data=data_object)
            # Plot the "centerline" with `plot`
            ax.plot('x', 'mean', color='black', data=data_object)
        补:np.linspace(start, stop, num=50)用法: 后面还有参数,但是应该遇不到!
            创建等差数列:
            前面两个参数分别是数列的开头和结尾,如果写出第三个参数,可以制定数列元素的个数,否则默认为50
 
    2.2 散点图:
        eg:
            x = np.arange(10)
            y = np.random.randn(10)
            plt.scatter(x, y, color='red', marker='+')
            补:ranger和numpy.aranger:
                *range(start, end, step),返回一个list对象也就是range.object,起始值为start,终止值为end,
                    但不含终止值,步长为step。只能创建int型list。
                *arange(start, end, step),与range()类似,也不含终止值。但是返回一个array对象。
                    需要导入numpy模块(import numpy as np或者from numpy import*),并且arange可以使用float型数据。
    
    2.3 条形图:
        条形图分两种,一种是水平的,一种是垂直的,
        eg:
            np.random.seed(1)
            x = np.arange(5)
            y = np.random.randn(5)
            
            # figsize设置figure大小
            # figsize=(width, height), 可以指定(w,h),也可以用figaspect(ratio)计算。创建指定宽度和高度的Figure
            # 从rcParams["figure.figsize"],取出height,并利用ratio = heught/width 计算出width,返回(width, height)
            fig, axes = plt.subplots(ncols=2, figsize=plt.figaspect(1./2))
            
            vert_bars = axes[0].bar(x, y, color='lightblue', align='center')  # bar是生成竖直柱状图
            horiz_bars = axes[1].barh(x, y, color='lightblue', align='center')  # barh生成水平柱状图
            
            #在水平或者垂直方向上画线
            axes[0].axhline(0, color='gray', linewidth=2)
            axes[1].axvline(0, color='gray', linewidth=2)
            补:
                plt.axhline(y=0.0, c="r", ls="--", lw=2)
                    y:水平参考线的出发点
                    c:参考线的线条颜色                    
                    ls->linestyle:参考线的线条风格                   
                    lw->linewidth:参考线的线条宽度
                同理:
                     plt.axvline(y=0.0, c="r", ls="--", lw=2)
                
        条形图还返回了一个Artists 数组,对应着每个条形,例如上图 Artists 数组的大小为5,
        我们可以通过这些 Artists 对条形图的样式进行更改,如下例:
            fig, ax = plt.subplots()
            vert_bars = ax.bar(x, y, color='lightblue', align='center')  # 生成一个条形图
            
            # We could have also done this with two separate calls to `ax.bar` and numpy boolean indexing.
            for bar, height in zip(vert_bars, y):   # 循环,每次生成一个条形图,这样可以控制每个条形图的样式
                if height < 0:
                    bar.set(edgecolor='darkred', color='salmon', linewidth=3)
                    
            plt.show()
            
    2.4 直方图
    
        np.random.seed(19680801)

        n_bins = 10
        x = np.random.randn(1000, 3)
        
        fig, axes = plt.subplots(nrows=2, ncols=2)
        ax0, ax1, ax2, ax3 = axes.flatten()
        
        colors = ['red', 'tan', 'lime']
        ax0.hist(x, n_bins, density=True, histtype='bar', color=colors, label=colors)
        ax0.legend(prop={'size': 10})
        ax0.set_title('bars with legend')
        
        ax1.hist(x, n_bins, density=True, histtype='barstacked')
        ax1.set_title('stacked bar')
        
        ax2.hist(x,  histtype='barstacked', rwidth=0.9)
        
        ax3.hist(x[:, 0], rwidth=0.9)
        ax3.set_title('different sample sizes')
        
        fig.tight_layout()
        plt.show()
        补:
            参数中density控制Y轴是概率还是数量,与返回的第一个的变量对应。histtype控制着直方图的样式,
            默认是 ‘bar’,对于多个条形时就相邻的方式呈现如子图1, ‘barstacked’ 就是叠在一起,如子图2、3。 
            rwidth 控制着宽度,这样可以空出一些间隙,比较图2、3. 图4是只有一条数据时。

    2.5 饼图
        labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
        sizes = [15, 30, 45, 10]
        explode = (0, 0.1, 0, 0)  # only "explode" the 2nd slice (i.e. 'Hogs')
        
        fig1, (ax1, ax2) = plt.subplots(2)
        ax1.pie(sizes, labels=labels, autopct='%1.1f%%', shadow=True)
        ax1.axis('equal')
        ax2.pie(sizes, autopct='%1.2f%%', shadow=True, startangle=90, explode=explode,
            pctdistance=1.12)
        ax2.axis('equal')   # 这个函数
        ax2.legend(labels=labels, loc='upper right')       
        
        补:
            饼图自动根据数据的百分比画饼.。labels是各个块的标签,如子图一。autopct=%1.1f%%表示格式化百分比精确输出,
            explode,突出某些块,不同的值突出的效果不一样。pctdistance=1.12百分比距离圆心的距离,默认是0.6.
        *.axes 和 .axis的区别:
            *ax.axes('equal')用来使X和Y上的轴间距相等,并设置xlim和ylim
            *ax.axis('equal')将横轴纵轴的定标系数设成相同值
            
               *axis中文为“轴”之意,在matlab中用于控制坐标轴的范围和样式(颜色等)
               axes是创建一个坐标系,而axis是对坐标系的简单控制,比如外形、比例等
        *legend解析:
            *通常是plt.legend() 和 ax.legend():
            表示生成一个图例:
                   loc:图例位置:
                         0:'best'
                         1: 'upper right'
                         2: 'upper left'
                         3:'lower left'
                         4: 'lower right'
                         5: 'right'
                         6: 'center left'
                         7: 'center right'
                         8: 'lower center'
                         9: 'upper center'
                         10: 'center'                   
                   fontsize:字体大小,
                   frameon:是否显示图例边框,
                   ncol:图例的列的数量,一般为1,
                   title:为图例添加标题
                   shadow:为图例边框添加阴影,
                   markerfirst:True表示图例标签在句柄右侧,false反之,
                   markerscale:图例标记为原图标记中的多少倍大小,
                   numpoints:表示图例中的句柄上的标记点的个数,一半设为1,
                   fancybox:是否将图例框的边角设为圆形
                   framealpha:控制图例框的透明度
                   borderpad: 图例框内边距
                   labelspacing: 图例中条目之间的距离
                   handlelength:图例句柄的长度
                   bbox_to_anchor: (横向看右,纵向看下),如果要自定义图例位置或者将图例画在坐标外边,用它,比如bbox_to_anchor=(1.4,0.8),这个一般配合着ax.get_position(),set_position([box.x0, box.y0, box.width*0.8 , box.height])使用
                   用不到的参数可以直接去掉,有的参数没写进去,用得到的话加进去     , bbox_to_anchor=(1.11,0)
            *plt.legend 和 ax.legend区别是legend生成的图以那个图的为基参照的,以整个画布还是你axes弄出来的图
    
    3.布局、图例说明、边界等:
        3.1 区间上下限:
            *一般绘画完成后,x,y的区间是会自己调整的,如果我们要自己设置x, y的范围,可以用下列的方式:
                ax.set_xlim([xmin,xmax])
                ax.set_ylim([ymin, ymax])
                ax.axis([xmin, xmax, ymin, ymax])  设置x, y轴区间
                ax.set_xlim(bottom = -10)    设置x轴下限
                ax.set_ylim(right =25)    设置y轴上限   
            *当然,不管设置什么,都可以用set函数,eg:
                ax.set(xlim=[], ylim=[], xlabel='', title='')
        
        3.2 图例说明:
            *就是用来标识不同图例的说明:
            *注意,如果在同一个ax上画几个图,在画他们的时候,分别指定他们label,那么我们
                 在ax.show() 面加一个ax.legend(),会默认自动设置一个图例说明,会根据你画的人是什么图,对应什么说明
            当然我们可以直接传入参数来控制图例说明的位置,图例说明的样式不需要我们管,python会自己搞!!!
    
        3.3 区间分段:
            有时候,需要设置坐标轴的刻度,这个时候我们需要用到set_xticks 或者 set(xtickw = )
            设置刻度值:set_xticklabels() 或者 set(xticklabels = )
            我们可以:
                ax2.set(xticks=x, xticklabels=fruit)  通常x, fruit都是元组或者是列表这种可迭代的数据集。
            eg:
                data = [('apples', 2), ('oranges', 3), ('peaches', 1)]
                fruit, value = zip(*data)
                
                fig, (ax1, ax2) = plt.subplots(2)
                x = np.arange(len(fruit))
                ax1.bar(x, value, align='center', color='gray')
                ax2.bar(x, value, align='center', color='gray')
                # ticks-->刻度
                ax2.set(xticks=x, xticklabels=fruit)
                
                #ax.tick_params(axis='y', direction='inout', length=10) #修改 ticks 的方向以及长度

        3.4 布局:
            通常处理于多个子图存在时,调整他们的间隔,位置,边距等等
            eg:子图与画板的外边间距
                fig, axes = plt.subplots(2,2,figsize = (9,9))
                fig.subplots_adjust(wspace=0.5, hspace=0.3,
                                    left=0.125, right=0.9,
                                    top=0.9,   bottom=0.1)
                # fig.tight_layout()  z这个可以自动调整布局,使不发生重叠!!
            
            *补:
               fig.subplots_adjust()  修改子图之间的布局,以下都是百分比!!!
                     wspace=0.5    修改子图水平之间的间隔,
                     hspace=0.3    修改子图垂直之间的间隔,
                     left=0.125  bottom=0.1  设置左边距、下边距
    注意!!!!!     right=0.9  top=0.9     这里设置的表示的是右、上边距为百分之10
                不知道如何布局时,用 fig.tight_layout()    自动布局,nice的很!!   
                
            *子图的内边距:
                内边距是子图的,也就是 Axes 对象,所以这样使用 ax.margins(x=0.1, y=0.1),
                当值传入一个值时,表示同时修改水平和垂直方向的内边距。

        3.5 轴相关
            eg:
                fig, ax = plt.subplots()
                ax.plot([-2, 2, 3, 4], [-10, 20, 25, 5])
                ax.spines['top'].set_visible(False)     #顶边界不可见
                ax.xaxis.set_ticks_position('bottom')  # ticks 的位置为下方,分上下的。
                ax.spines['right'].set_visible(False)   #右边界不可见
                ax.yaxis.set_ticks_position('left')  
                
                # "outward"
                # 移动左、下边界离 Axes 10 个距离
                #ax.spines['bottom'].set_position(('outward', 10))
                #ax.spines['left'].set_position(('outward', 10))
                
                # "data"
                # 移动左、下边界到 (0, 0) 处相交
                ax.spines['bottom'].set_position(('data', 0))
                ax.spines['left'].set_position(('data', 0))
                
                # "axes"
                # 移动边界,按 Axes 的百分比位置
                #ax.spines['bottom'].set_position(('axes', 0.75))
                #ax.spines['left'].set_position(('axes', 0.3))

--------------------------------------Tkinter 图形页面开发库-----------------------------
网址:https://blog.csdn.net/ahilll/article/details/81531587?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-4&spm=1001.2101.3001.4242
1.简介:
    图形用户界面(Graphical User Interface,简称 GUI),tkinter是python 自带的,可以编辑的GUI界面

2.Tkinter 控件详写介绍:
    2.1 常用窗口部件及简要说明: Tkinter支持16个核心的窗口部件
        *Button: 一个简单的按钮,用来执行命令或别的操作。
        *Canvas: 组织图形。这个部件可以用来绘制图表和图,创建图形编辑器,实现定制窗口部件。
        *Checkbutton: 代表一个变量,它有两个不同的值,点击这个按钮将会在这两个值之间切换。
        *Entry: 文本输入域。
        *Frame: 一个容器窗口部件,帧可以有边框和背景,当创建一个应用程序或dialog(对话)版面时,帧用来组织其他的窗口部件
        *Label: 显示有一个文本或图像
        *Listbox: 显示供选方案的一个列表,listbox能够被配置来得到radiobutton或checklist的行为。
        *Menu:菜单条。用来实现下拉和弹出式菜单。
        *Menubutton:菜单按钮。用来实现下拉式菜单。
        *Message:显示一文本。类似label窗口部件,但是能够自动地调整文本到给定的宽度或比率。
        *Radiobutton:代表一个变量,它可以有多个值中的一个。点击它将为这个变量设置值,并且清除与这同一变量相关的其它radiobutton。
        *Scale:允许你通过滑块来设置一数字值。
        *Scrollbar:为配合使用canvas, entry, listbox, and text窗口部件的标准滚动条。  
        *Text:格式化文本显示。允许你用不同的样式和属性来显示和编辑文本。同时支持内嵌图象和窗口。
        *Toplevel:一个容器窗口部件,作为一个单独的、最上面的窗口显示。
        *messageBox:消息框,用于显示你应用程序的消息框。(Python2中为tkMessagebox)
            -***注意在Tkinter中窗口部件类没有分级;所有的窗口部件类在树中都是兄弟关系。
            
        *补:
            -global关键字的作用是可以申明一个局部变量为全局变量。
            -stringvar():需要跟踪变量的值的变化,以保证值的变更随时可以显示在界面上。
            -x = StringVar() # 保存一个 string 类型变量, 默认值为""
            -x = IntVar() # 保存一个整型变量, 默认值为0
            -x = DoubleVar() # 保存一个浮点型变量, 默认值为0.0
            -x = BooleanVar() # 保存一个布尔型变量, 返回值为 0 (代表 False) 或 1 (代表 True)
            -要得到其保存的变量值, 使用它的 get() 方法即可. 
            -要设置其保存的变量值, 使用它的 set() 方法即可.

3.实践学习:
    3.1 创建主窗口及Label部件(标签)创建使用:
        import tkinter as tk

        # 第一步,实例化object,创建窗口window
        window = tk.Tk()
        
        # 第二步,给窗口的可视化起名字:
        window.title("My Window")
        
        # 第三步,设定窗口大小:
        window.geometry("500x300")   # -->这里的乘是小x
        
        # 第四步,在图像界面上设定标签:
        l = tk.Label(window, text='你好!this is qtt', background='green', font=('Arial', 12), width=30, height=2)
        # # 说明: bg为背景,font为字体,width为长,height为高,这里的长和高是字符的长和高,比如height=2,就是标签有2个字符这么高
        
        # 第五步,放置标签:
        l.pack()     # Label内容content区域放置位置,自动调节尺寸
        # 放置Label的方法有: 1)l.pack(); 2)l.place();
        
        # 第六步,主窗口的循环显示
        window.mainloop()
        # 注意,loop因为是循环的意思,window.mainloop就会让window不断的刷新,如果没有mainloop,就是一个静态的window,传入进去的值就不会有循环,mainloop就相当于一个很大的while循环,有个while,每点击一次就会更新一次,所以我们必须要有循环
        # 所有的窗口文件都必须有类似的mainloop函数,mainloop是窗口文件的关键的关键
        
    3.2 Button窗口部件:
        *简单说明:
            Button(按钮)可以包含文本或图像,并且你能够将按钮与一个Python函数或者方法相关联。
            当这个按钮按下的时候,Tkinter自动调用相关联的函数或方法。默认情况下,Tab键用于将焦点移动到下一个按钮部件
        *eg:
            # 第1步,实例化object,建立窗口window
            window = tk.Tk()
            
            # 第2步,给窗口的可视化起名字
            window.title('My Window')
            
            # 第3步,设定窗口的大小(长 * 宽)
            window.geometry('500x300')  # 这里的乘是小x
            
            # 第4步,在图形界面上设定标签
            var = tk.StringVar()  # 将label标签的内容设置为字符类型,用var来接收hit_me函数的传出内容用以显示在标签上
            l = tk.Label(window, textvariable=var, bg='green', fg='white', font=('Arial', 12), width=30, height=2)
            # 说明: bg为背景,fg为字体颜色,font为字体,width为长,height为高,这里的长和高是字符的长和高,比如height=2,就是标签有2个字符这么高
            l.pack()
            
            # 定义一个函数功能(内容自己自由编写),供点击Button按键时调用,调用命令参数command=函数名
            on_hit = False
            
            
            def hit_me():
                global on_hit
                if on_hit == False:
                    on_hit = True
                    var.set('you hit me')
                else:
                    on_hit = False
                    var.set('')
            
            
            # 第5步,在窗口界面设置放置Button按键
            b = tk.Button(window, text='hit me', font=('Arial', 12), width=10, height=1, command=hit_me)
            b.pack()
            
            # 第6步,主窗口循环显示
            window.mainloop()

    3.3 Entry窗口部件:
        *说明:
            Entry是tkinter中提供的一个单文本输入域,用来输入显示一行文本,收集键盘输入(类似HTML中的text)
        *eg:
            window = tk.Tk()
            window.title('My window')
            window.geometry('500x300')
            
            # 在图形界面上设定输入框控件entry并放置控件
            e1 = tk.Entry(window, show='*', font=('Arial', 14))  # 显示成密文形式
            e2 = tk.Entry(window, show=None, font=('Arial', 14))  # 显示成明文形式
            e1.pack()
            e2.pack()
            
            # 第6步,主窗口循环显示
            window.mainloop()
    
    3.4 Text窗口部件:
        *说明:
            Text是tkinter类中提供的一个多行文本区域,显示多行文本,可用来收集(或显示)用户输入的文字(类似HTML中的textarea),格式化文本显示,
            允许你用不同的样式和属性来显示和编辑文本,同时支持内嵌图像和窗口。
        *eg:
            window = tk.Tk()
            window.title('My window')
            window.geometry('500x300')
            
            e = tk.Entry(window, show=None)
            e.pack()
            
            def insert_point():  # 在鼠标焦点处插入输入内容
                var = e.get()
                t.insert('insert', var)
            
            def insert_end():    # 在文本内容最后插入内容
                var = e.get()
                t.insert('end', var)
            
            # 设置两个按钮分别触发两种情况
            b1 = tk.Button(window, text='insert_point', width=10, height=2, command=insert_point)
            b2 = tk.Button(window, text='insert_end', width=10, height=2, command=insert_end)
            
            b1.pack()
            b2.pack()
            
            t = tk.Text(window, height=3)
            t.pack()
            # 第6步,主窗口循环显示
            window.mainloop()
        
    3.5 Listbox窗口部件:
        *说明:
            Listbox是tkinter类中提供的列表部件,显示供选方案的一个列表。listbox能够被配置来得到
            radiobutton或checklist行为
        *eg:
            window = tk.Tk()
            window.geometry('500x300')
            window.title('My tkinter')
            
            var1 = tk.StringVar()
            l=tk.Label(window, textvariable=var1, bg='green', fg='yellow', font=('Arial', 12), width=20)
            l.pack()
            
            def print_selection():
                value = lb.get(lb.curselection())
                var1.set(value)
            
            b1 = tk.Button(window, text='print_selection', command=print_selection, width=15, height=2)
            b1.pack()
            
            var2 = tk.StringVar()
            var2.set([1, 2, 3, 4])
            
            # 创建一个listbox并为其添加内容
            lb = tk.Listbox(window, listvariable=var2)
            
            list_items = [11, 22, 33, 44]
            for item in list_items:
                lb.insert('end', item)  # 从最后一个位置开始加入值
            lb.insert(1, 'first')   # 在1号为插入‘frist’字符
            lb.insert(2, 'second')   # 在二号位置插入‘second’
            lb.delete(2)    # 删除二号位置的字符
            lb.pack()
            
            # 第6步,主窗口循环显示
            window.mainloop()
            
    3.6 Radiobutton窗口部件
        *简单说明“
            Radiobutton: 代表一个变量,它可以有多个值中的一个,点击它将为这个变量设置值,
                         并且清除与这同一变量相关的其它radiobutton
        eg:
            window = tk.Tk()
            window.geometry('500x300')
            window.title('万智粱 eat shit')
            
            l = tk.Label(window, text='empty', width=30, bg='red')
            l.pack()
            
            var1 = tk.StringVar()  # 定义一个var用来将radiobutton的值和Label的值联系在一起。
            
            def select_value():
                # config --> 将资源的值指定为关键字的value
                l.config(text='you have selected ' + var1.get())
            
            # 创建三个radiobutton选项,其中variable=var, value='A'的意思是:当我们鼠标选中了其中一个选项,把value的值A放到变量var中,然后赋值给variable中
            r1 = tk.Radiobutton(window, text='Option A', variable=var1, value='A', command=select_value)
            r1.pack()
            r2 = tk.Radiobutton(window, text='Option B', variable=var1, value='B', command=select_value)
            r2.pack()
            r3 = tk.Radiobutton(window, text='Option C', variable=var1, value='C', command=select_value)
            r3.pack()
            
            window.mainloop()

    3.7 Checkbutton窗口部件
        *说明:
            它代表一个变量,它有两个不同的值,点击这个按钮将会在这两个值间切换,选择和取消选择
        *eg:
            window = tk.Tk()
            window.geometry('500x300')
            window.title('万智粱 eat shit')
            
            l = tk.Label(window, text='empty', width=30, bg='yellow')
            l.pack()
            
            
            def print_selection():
                if (var1.get() == 1) and (var2.get() == 0):
                    l.config(text='I love only Python ')
                elif (var1.get() == 0) and (var2.get() == 1):
                    l.config(text='I love only Java ')
                elif (var1.get() == 0) and (var2.get() == 0):
                    l.config(text='I do not love either')
                else:
                    l.config(text='I love both')
            
            var1 = tk.IntVar()   # 定义var1和var2整型变量用来存放选择行为返回值
            var2 = tk.IntVar()
            
            # variable:
                    # 1. 将 Checkbutton 跟一个 Tkinter 变量关联
                    # 2. 当按钮按下时,该变量在 onvalue 和 offvalue 之间切换
                    # 3. 这个切换的过程是完全自动的
            c1 = tk.Checkbutton(window, text='Python', variable=var1, onvalue=1, offvalue=0, command=print_selection)
            c1.pack()
            c2 = tk.Checkbutton(window, text='Java', variable=var2, onvalue=1, offvalue=0, command=print_selection)
            c2.pack()
            
            window.mainloop()

    3.8 Scale窗口部件:
        *说明:
            Scale: 尺度(拉动条),允许你通过滑块来设置一数字值。
        *eg:
            # 第1步,实例化object,建立窗口window
            window = tk.Tk()
             
            # 第2步,给窗口的可视化起名字
            window.title('My Window')
             
            # 第3步,设定窗口的大小(长 * 宽)
            window.geometry('500x300')  # 这里的乘是小x
             
            # 第4步,在图形界面上创建一个标签label用以显示并放置
            l = tk.Label(window, bg='green', fg='white', width=20, text='empty')
            l.pack()
             
            # 第6步,定义一个触发函数功能
            def print_selection(v):
                l.config(text='you have selected ' + v)
            # 第5步,创建一个尺度滑条,长度200字符,从0开始10结束,以2为刻度,精度为0.01,触发调用print_selection函数
            s = tk.Scale(window, label='try me', from_=0, to=10, orient=tk.HORIZONTAL, length=200, showvalue=0,tickinterval=2, resolution=0.01, command=print_selection)
            s.pack()
            window.mainloop()
            
    3.9 Canvas窗口部件:
        *说明:
            Canvas: 画布,提供绘图功能(直线、椭圆、多边形、矩形)可以包含图形或位图,
                    用来绘制图表和图,创建图形编辑器,实现定制窗口部件。
        *什么时候用到:
            比如用户交互界面等,需要提供设计的图标、图形、logo等信息是可以用到画布的。
        *里面的简单方法:
            create_arc:绘制弧。
            create_bitmap:绘制位图。
            create_image:绘制图片。           
            create_line():绘制直线。
            create_polygon:绘制多边形。
            create_text:绘制文字。
            create_window:绘制组件。
        *eg:
            window = tk.Tk()
            window.geometry('500x300')
            window.title('My tkinter')
            # 在图形界面上创建一个 300*300 的画布并放置各种元素
            canvas = tk.Canvas(window, height=300, width=300, bg='yellow')
            # 说明照片位置, 并导入图片到画布上
            # 锚点定点及anchor的值:N、S、W、E、NW、NE、SE、SW、center  -->小写也是可以的
                # 其实说白了,就是以图片的哪个位置为中心,将图片放在canvas的坐标处
            image_file = tk.PhotoImage(file=R'E:\Python\PlaneDemo\feiji\玩家飞机1.png')  # 照片的绝对路径
            image = canvas.create_image(200, 0, image=image_file, anchor='n')   # 图片锚定点(n图片顶端的中间位置)放在画布(200,0)坐标处
            # 定义多边形参数,然后在画布上画出指定图形
            x0, y0, x1, y1 = 100, 100, 150, 150
            line = canvas.create_line(x0-10, y0-10, x1-20, y1-20)  # 画直线
            arc = canvas.create_arc(x0, y0+50, x1, y1+50, start=0, extent=250)   # 画扇形,从0度打开到180结束
            
            canvas.pack()
            # 触发函数,可以移动指定图形指定距离
            def moveit():
                canvas.move(image, 30, 0)
            # 定义一个按钮来连接函数
            b = tk.Button(window, text='move image', command=moveit, bg='red')
            b.pack()
            
            window.mainloop()
    
    3.10 Menu窗口部件:
        *说明:
            Menu: 菜单条, 用来实现下拉和弹出式菜单,点下菜单后弹出的一个选项列表,用户可以从中选择
        *eg:
            window = tk.Tk()
            window.geometry('500x300')
            window.title('My tkinter')
            
            l = tk.Label(window, bg='yellow', text='     ')
            l.pack()
            
            counter = 0
            def do_():
                global counter
                l.config(text='do ' + str(counter))
                counter += 1
                pass
            # 创建一个菜单栏, 这里我们可以把他理解成一个容器,在窗口的上方
            menubar = tk.Menu(window)
            # 创建一个菜单项(默认不下拉,下拉内容包括New, Open, Save, Exit功能项)
            filemenu = tk.Menu(menubar, tearoff=0)
            # 将上面的定义的空菜单命名为File,放在菜单栏中, 就是装入,那个容器中
            menubar.add_cascade(label='File', menu=filemenu)
            
            # 在File中加入New, Open, Save等小菜单,即我们平时看到的下拉菜单,每一个小菜单对应命令操作
            filemenu.add_command(label='New', command=do_)
            filemenu.add_command(label='Open', command=do_)
            filemenu.add_command(label='Save', command=do_)
            filemenu.add_separator()   # 添加一条分界线
            filemenu.add_command(label='Exit', command=window.quit)  # 用tkinter里面自带的quit()函数----> 退出
            
            # 又创建一个菜单项,其余的和上面相似
            editmenu = tk.Menu(menubar, tearoff=0)
            
            menubar.add_cascade(label='Edit', menu=editmenu)
            editmenu.add_command(label='Cut', command=do_)
            editmenu.add_command(label='Copy', command=do_)
            editmenu.add_command(label='Paste', command=do_)
            
            submenu = tk.Menu(filemenu)
            filemenu.add_cascade(label='Import', menu=submenu, underline=0)
            
            submenu.add_command(label='submenu_1', command=do_)
            
            # 创建菜单栏后,配置让菜单栏menubar显示出来!!!!
            window.config(menu=menubar)
            window.mainloop()

    3.11 Frame窗口部件:
        *说明:
            Frame:框架,用来承载其他的GUI元素,就是一个容器,是一个在Windows上分离小区域的部件,它将Windows分成不同的区,然后存放不同的其他部件。
                    同时一个Frame上也能在分成两个Frame,Frame可以认为是一种容器
        *eg:
            window = tk.Tk()
            window.geometry('500x300')
            window.title('My tkinter')
            
            tk.Label(window, text='on the window', bg='red', font=('Arial', 16)).pack()
            
            frame = tk.Frame(window)
            frame.pack()
            
            frame_l = tk.Frame(frame)
            frame_r = tk.Frame(frame)
            frame_l.pack(side='left')
            frame_r.pack(side='right')
            
            tk.Label(frame_l, text='on the frame_l1', bg='green').pack()
            tk.Label(frame_l, text='on the frame_l2', bg='green').pack()
            tk.Label(frame_l, text='on the frame_l3', bg='green').pack()
            tk.Label(frame_r, text='on the frame_r1', bg='yellow').pack()
            tk.Label(frame_r, text='on the frame_r2', bg='yellow').pack()
            tk.Label(frame_r, text='on the frame_r3', bg='yellow').pack()

            window.mainloop()
            
    3.12 messageBox窗口部件:
        *说明:
            messageBox:消息框,用于显示你应用程序的消息框,其实这里的messageBox就是我们平时看到的弹窗。我们首先需要定义一个触发功能,来触发这个弹窗,
                        这里就放上以前学过的button按钮,通过触发功能,调用messageBox
        *messageBox提示信息的几种形式:
            -tkinter.messagebox.showinfo(title='Hi', message='你好!')            # 提示信息对话窗
            -tkinter.messagebox.showwarning(title='Hi', message='有警告!')       # 提出警告对话窗
            -tkinter.messagebox.showerror(title='Hi', message='出错了!')         # 提出错误对话窗
            -print(tkinter.messagebox.askquestion(title='Hi', message='你好!'))  # 询问选择对话窗return 'yes', 'no'
            -print(tkinter.messagebox.askyesno(title='Hi', message='你好!'))     # return 'True', 'False'
            -print(tkinter.messagebox.askokcancel(title='Hi', message='你好!'))  # return 'True', 'False'
        *eg:
            def hit_me():
                tkinter.messagebox.showinfo(title='Hi', message='你好!')              # 提示信息对话窗
                # tkinter.messagebox.showwarning(title='Hi', message='有警告!')       # 提出警告对话窗
                # tkinter.messagebox.showerror(title='Hi', message='出错了!')         # 提出错误对话窗
                # print(tkinter.messagebox.askquestion(title='Hi', message='你好!'))  # 询问选择对话窗return 'yes', 'no'
                # print(tkinter.messagebox.askyesno(title='Hi', message='你好!'))     # return 'True', 'False'
                # print(tkinter.messagebox.askokcancel(title='Hi', message='你好!'))  # return 'True', 'False'
 
            # 第4步,在图形界面上创建一个标签用以显示内容并放置
            tk.Button(window, text='hit me', bg='green', font=('Arial', 14), command=hit_me).pack()

    3.13 窗口部件放置的三种方式pack/grid/place:
        1. grid:the Grid Geometry Manager:
            *grid是方格,所以所有的内容会被放在这些规律的方格中。
                -例如:
                for i in rang(3):
                    for j in rang(3):
                        tk.Label(window, text=1).grid(row=i, column=j, padx=10, pady=10, ipady=10)
                -上面的代码就是创建一个三行三列的表格, 其中grid就是用表格的形式定位的。这里的参数:
                    row-->行                               column-->列
                    padx-->单元格左右间距                    pady-->单元格上下间距
                    ipadx-->单元格内部元素与单元格的左右间距    ipady-->单元格内部元素与单元格的上下间距
        
        2.pack:
            *我们通常用的pack(),它会按照上下左右的方式排列,
                例如:
                tk.Label(window, text='p', fg='red').pack(side='top')  
                tk.Label(window, text='p', fg='red').pack(side='bottom')  
                tk.Label(window, text='p', fg='red').pack(side='left')
                tk.Label(window, text='p', fg='red').pack(side='right')
        
        3.place:
            *就是给精确的坐标来定位,如此处给的(50,100), 就是将这个部件放在坐标为(x=50. y=100)的这个位置,后面的参数anchor='nw',
            就是前面讲的西北角。eg:   
                tk.Lable(window, text='P1', font=('Arial', 20)).place(x=50, y=100, anchor='nw')
                
4.综合练习,用户登录窗口:
    编写一个用户登录界面,用户可以登录账户信息,如果账户已经存在,可以直接登录,登录名或者登录密码输入错误会提示,如果账户不存在,
    提示用户注册,点击注册进去注册页面,输入注册信息,确定后便可以返回登录界面进行登录。
    
    *代码:
        
                          
        


'''
# import matplotlib.pyplot as plt
# import numpy as np
# import random
# labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
# sizes = [15, 30, 45, 10]
# explode = (0, 0.1, 0, 0)  # only "explode" the 2nd slice (i.e. 'Hogs')
#
# fig1, (ax1, ax2) = plt.subplots(2)
# ax1.pie(sizes, labels=labels, autopct='%1.1f%%', shadow=True)
# ax1.axis('equal')
# ax2.pie(sizes, autopct='%1.2f%%', shadow=True, startangle=90, explode=explode,
#     pctdistance=1.12)
# ax2.axis('equal')
# ax2.legend(labels=labels, loc='upper right')
#
# plt.show()

import tkinter as tk
import tkinter.messagebox
import pickle

window = tk.Tk()
window.title('Wellcome to Qtt不甜 Website')
window.geometry('400x300')

canvas = tk.Canvas(window, width=400, height=135, bg='green')
image_file = tk.PhotoImage(file=R'E:\Python\PlaneDemo\feiji\玩家飞机1.png')
image = canvas.create_image(200, 0, anchor='n', image=image_file)
canvas.pack(side='n')
tk.Label(window, text='Wellcome', font=('Arial', 16)).pack()

tk.Label(window, text='User name:', font=('Arial', 12)).place(x=10, y=170)
tk.Label(window, text='Paseword:', font=('Arial', 12)).place(x=10, y=210)

var_user_name = tk.StringVar()
var_user_name.set('[email protected]')
entry_user_name = tk.Entry(window, textvariable = var_user_name, font=('Arial', 12)).place(x=120, y=175)

var_user_pwd = tk.StringVar()
entry_user_pwd = tk.Entry(window, textvariable= var_user_pwd, font=('Arial', 12), show='*').place(x=120, y=215)

def usr_login():
    usr_name = var_user_name.get()
    usr_pwd = var_user_pwd.get()
    try:
        with open


          
          
          
          
          
          
          
          
          
          
          
          

你可能感兴趣的:(python)