文章目录

  • ----------------------------------基础----------------------------------
  • 1.变量
  • 2.运算符
  • 3.输入和输出
  • 总结
  • 4.流程控制结构
  • 5.高级数据类型
  • 总结
  • 6.函数(上)
    • 定义
    • 函数的定义、调用、参数
    • 参数的分类——必选参数、默认参数【缺省参数】、可选参数、关键字参数
    • 函数返回值
    • 函数嵌套
  • 总结
  • 7.函数(下)
    • 7.1函数的基本类型
    • 7.2全局变量和局部变量
    • 7.3引用传值
    • 7.4匿名函数
    • 7.5递归函数
  • 总结
  • 8.内置函数
    • 8.1内置函数功能列表
    • 8.2数学运算
    • 8.3类型转换运算
    • 8.4序列操作函数
    • 8.5内置函数set
  • 总结
  • --------------------------------面向对象--------------------------------
  • 1.面向对象(上)
    • 1.1定义
    • 1.2类和对象
    • 1.3定义类和创建对象、实例方法和属性、init方法
    • 1.4 init方法
    • 1.5 self理解
    • 1.6 魔术方法
  • 2.面向对象(中)
    • 2.1析构方法
    • 2.2单继承
    • 2.3多继承
    • 2.4间接继承
    • 2.5重写和调用父类方法
    • 2.6 类属性和实例属性
    • 2.7类方法和静态方法
    • 2.8三种方法对比
    • 2.9多态
    • 2.10 三大特征(面向对象)
  • 3.面向对象(下)
    • 3.1私有化属性
    • 3.2私有化方法
    • 3.3Property属性函数(意义不大)
    • 3.4__new__方法
    • 3.5单例模式
  • ------------------------------------异常处理--------------------------------------
  • 1.异常处理(1)
  • 2.异常处理(2)
  • 3.异常处理(3)
  • 4.动态添加属性和方法(了解)
  • 5. ___slots_ __属性
  • 6.文件操作
    • 6.1文件读写
    • 6.2备份文件
    • 6.3文件定位(了解)
    • 6.4模块导入
  • 7.常见模块
  • 8.模块的制作、发布、安装
    • 8.1模块的制作
    • 8.2模块的发布
    • 8.3模块的安装
  • ------------------------------------内存管理---------------------------------
  • 1.引用计数法
  • 2.标记清除、分代收集算法
  • 3.小整数和大整数对象池(内存优化)
  • 4.规范
  • 5.命令行参数_sys
  • 6.命令行参数_argparse


----------------------------------基础----------------------------------

1.变量

  • 元组类型

    b = ()
    
  • 列表类型

    b = []
    
  • 字典类型

    b = {}
    
  • 简单类型

    b = 123
    a =123‘
    c = True
    d = 5.0
    
  • 命名规则
    1、开头必须以字母或下划线_开头
    2、区分大小写
    3、除了开头,其余字母、数字、下划线均可
    4、python关键字不能用作变量名

  • 命名规范

2.运算符

  • 算术运算符
  • 比较运算符
  • 逻辑运算符

    优先级:() > not > and > or
  • 赋值运算符

3.输入和输出

  • 输出

    • %占位符
    #输出 %占位符
    name = '张扬'
    classPro = '清华附中3班'
    age = 7  #整数为%d
    print('我的名字是%s:来自[%s],今年%d岁了'%(name,classPro,age))
    

    • .format()
    name = '张扬'
    classPro = '清华附中3班'
    age = 7  #整数为%d
    print('我的名字是{}:来自[{}],今年{}岁了'.format(name,classPro ,age))
    
    • \n换行符
  • 输入

    # input输入的一定是字符串形式 如果必须要求输入其他类型的数 
    # 比如%d要求整数 就用int(input())转换
    name = input("请输入你的姓名:")
    

总结

4.流程控制结构

  • 选择控制 if-elif-else

    score = int(input('请输入成绩:'))
    if score > 70:
    	print('成绩可以')
    elif score >60:
    	print('及格了')
    else:
    	print('没及格,延毕!')
    
  • 循环控制

    • for循环
      for i in range(1,101):
      	print(i , end = " ")
      
    • while循环
      row = 1
      while row<9:
      	print(row)
      	row += 1
      
    • break 跳出当前循环
    • continue 执行当前循环的下一次

    注:许多案例,如九九乘法表、直角三角形等等

5.高级数据类型

  • 序列:一组按照顺序排列的值(数据集合)

    • 索引/下表(默认从0开始)

    • 切片:截取字符串中的其中一段内容,[start : end :step] (step默认为1,end默认为不包含)

    • 1:字符串(不可变)

      Test='python'
      # print(type(Test))
      # print('获取第一个字符%s'%Test[0])
      # print('获取第二个字符%s'%Test[1])
      # for item in Test:
      #     print(item,end=' ')
      name='peter'
      # print('姓名首字母转换大写%s'%name.capitalize()) capitalize 首字母变大写
      a='     hello       '
      # b=a.strip() #去除字符串中两边的空格
      # print(a)
      # print(a.lstrip()) #删除左边的空格
      # print(a.rstrip()) #删除右边的空格
      # 复制字符串
      # print('a的内存地址%d'%id(a)) #id函数 可以查看一个对象的内存地址
      # b=a #在此只是把a对象的内存地址赋给了b
      # print('a的内存地址%d'%id(a))
      # print(b)
      # dataStr='I love Python'
      # print(dataStr.find('M')) #find函数可以查找目标对象在序列对象中的为值,如果没找到就返回-1
      # print(dataStr.index('W')) #检测字符串中是否包含子字符串 返回的是下标值
      # index如果没有找到对象的数据 便会报异常,而find函数不会,找不到返回-1
      # print(dataStr.startswith('I'))  #判断开头
      # print(dataStr.endswith('n'))#判断结尾
      #
      # print(dataStr.lower()) #转换成小写
      # print(dataStr.upper())#转换成大写
      
      strMsg='hello world'
      # slice [start:end:step] 左闭右开  start<=value<end 范围
      # print(strMsg) #输出完整的数据
      # print(strMsg[0])
      print(strMsg[2:5]) #2-5下标之间的数据
      print(strMsg[2:]) #第三个字符到最后
      print(strMsg[:3]) #1-3    strMsg[0:3]=strMsg[:3]
      print(strMsg[::-1]) #倒叙输出  负号表示方向  从右边往左去遍历
      # 共有方法  +  *  in
      # 字符串合并
      strA='人生苦短'
      strB='我用Python'
      # list 合并
      listA=list(range(10))
      listB=list(range(11,20))
      print(listA+listB)
      # print(strA+strB)
      # 复制 *
      # print(strA*3)
      # print(listA*3)
      # in  对象是否存在 结果是一个bool值
      print('我' in strA) #False
      print(9 in listA)  #False
      dictA={"name":"peter"}
      print("name" in dictA)
      
      

    • 2:列表(可变)
    • 2.1:支持增删改查
    • 2.2:列表中的数据是可以变化的【数据项可以变化,内存地址不会改变】
    • 2.3:用[] 来表示列表类型,数据项之间用逗号来分割,注意:数据项可以是任何类型的数据
    • 2.4:支持索引和切片来进行操作
      # li=[] #空列表
      # li=[1,2,3,"你好"]
      # print(len(li)) #len函数可以获取到列表对象中的数据个数
      # strA='我喜欢python'
      # print(len(strA))
      # print(type(li))
      # 查找
      listA=['abcd',785,12.23,'qiuzhi',True]
      # print(listA) #输出完整的列表
      # print(listA[0]) #输出第一个元素
      # print(listA[1:3]) #从第二个开始到第三个元素
      # print(listA[2:]) #从第三个元素开始到最后所有的元素
      # print(listA[::-1]) #负数从右像左开始输出
      # print(listA*3) #输出多次列表中的数据【复制】
      # print('--------------增加-----------------------')
      # print('追加之前',listA)
      # listA.append(['fff','ddd']) #追加操作
      # listA.append(8888)
      # print('追加之后',listA)
      # listA.insert(1,'这是我刚插入的数据') #插入操作 需要执行一个位置插入
      # print(listA)
      # rsData=list(range(10)) #强制转换为list对象
      # print(type(rsData))
      # listA.extend(rsData) #拓展  等于批量添加
      # listA.extend([11,22,33,44])
      # print(listA)
      # print('-----------------修改------------------------')
      # print('修改之前',listA)
      # listA[0]=333.6
      # print('修改之后',listA)
      listB=list(range(10,50))
      
      print('------------删除list数据项------------------')
      print(listB)
      # del listB[0] #删除列表中第一个元素
      # del listB[1:3] #批量删除多项数据 slice
      # listB.remove(20) #移除指定的元素  参数是具体的数据值
      listB.pop(1) #移除制定的项  参数是索引值
      print(listB)
      
      print(listB.index(19,20,25))  #返回的是一个索引下标
      

    • 3:元组(不可变)

    • 3.1:不可变

    • 3.2:用()创建元组类型,数据项用逗号来分割

    • 3.3:可以是任何的类型

    • 3.4:当元组中只有一个元素时,要加上逗号,不然后解释器会当做其他类型来处理

    • 3.5:同样可是支持切片操作

      # 元组的创建 不能进行修改
      tupleA=() #空元组
      # print(id(tupleA))
      tupleA=('abcd',89,9.12,'peter',[11,22,33])
      # print(id(tupleA))
      # print(type(tupleA))
      # print(tupleA)
      # 元组的查询
      # for item in tupleA:
      # #     print(item,end=' ')
      # print(tupleA[2:4])
      # print(tupleA[::-1])
      
      # print(tupleA[::-2]) #表示反转字符串 每隔两个取一次
      # # print(tupleA[::-3]) #表示反转字符串 每隔三个取一次
      # # print(tupleA[-2:-1:]) #倒着取下标 为-2 到 -1 区间的
      # # print(tupleA[-4:-2:]) #倒着取下标 为-2 到 -1 区间的
      
      # tupleA[0]='PythonHello'  #错误的
      # tupleA[4][0]=285202  #可以对元组中的列表类型的数据进行修改
      # print(tupleA)
      # print(type(tupleA[4]))
      
      tupleB=('1',) # 当元组中只有一个数据项的时候,必须要在第一个数据项后面加上 逗号
      # print(type(tupleB))
      tupleC=(1,2,3,4,3,4,4,1)   #tuple(range(10))
      
      print(tupleC.count(4)) #可以统计元素出现的次数
      
      
  • 字典

    • 4.1:不是序列类型 没有下标的概念,是一个无序的 键值集合,是内置的高级数据类型
    • 4.2:用{} 来表示字典对象,每个键值对用逗号分隔
    • 4.3:键 必须是不可变的类型【元组、字符串】,值可以是任意的类型
    • 4.4: 每个键必定是惟一的,如果存在重复的键,后者会覆盖前者
    # 如何创建字典
    dictA={"pro":'艺术','shcool':'北京电影学院'} #空字典
    # 添加字典数据
    dictA['name']='李易峰'  #key:value
    dictA['age']='30'
    dictA['pos']='歌手'
    #结束添加
    # print(dictA) #输出完整的字典
    # print(len(dictA))  #数据项长度
    # print(type(dictA))
    
    # print(dictA['name']) #通过键获取对应的值
    dictA['name']='谢霆锋'  #修改键对应的值
    dictA['shcool']='香港大学'
    dictA.update({'height':1.80}) #可以添加或者更新
    print(dictA)
    
    # 获取所有的键
    print(dictA.keys())
    # 获取所有的值
    print(dictA.values())
    # 获取所有的键和值
    print(dictA.items())
    for key,value in dictA.items():
        print('%s==%s'%(key,value))
    
    # 删除操作
    del dictA['name']  通过指定键进行删除
    dictA.pop('age')   通过指定键进行删除
    print(dictA)
    # 如何排序 按照key排序
    print(sorted(dictA.items(),key=lambda d:d[0]))
    # 按照value排序
    print(sorted(dictA.items(),key=lambda d:d[1]))
    # 字典拷贝
    import copy
    # dictB=copy.copy(dictA) #浅拷贝
    dictC=copy.deepcopy(dictA) #深拷贝
    print(id(dictC))
    print(id(dictA))
    # dictB['name']='peter'
    dictC['name']='刘德华'
    print(dictC)
    print(dictA)
    
    
  • 公用方法

总结

6.函数(上)

  • 定义

    什么是函数:一系列Python语句的组合,可以在程序中运行一次或者多次。
    一般是完成具体的独立的功能
    为什么要使用函数:
    	代码的复用最大化以及最小化冗余代码,整体代码结构清晰,问题局部化
    函数定义:
    	def 函数名():
    		函数体[一系列的python语句,表示独立的功能]
    函数的调用:
    	本质上就是去执行函数定义里面的代码块,在调用函数之前必须先定义。
    
  • 函数的定义、调用、参数

    # print('小张的身高是%f'%1.73)
    # print('小张的体重是%f'%160)
    # print('小张的爱好是%s'%'唱歌')
    # print('小张的身高是%s'%'计算机信息管理')
    #处理其他的逻辑信息
    # 多次去打印出小张的信息
    print('---------------多次输出相同的信息---------------------')
    # print('小张的身高是%f'%1.73)
    # print('小张的体重是%f'%160)
    # print('小张的爱好是%s'%'唱歌')
    # print('小张的专业是%s'%'计算机信息管理')
    # 针对上面的场景 就需要进一步的去优化代码【方案:封装函数】
    # 函数的定义
    # def 函数名(参数列表):0-n 个
    #     代码块
    
    def printInfo():
        '''
        这个函数是用来打印个人信息的 是对小张信息显示的组合
        :return:
        '''
        # 函数代码块
        print('小张的身高是%f' % 1.73)
        print('小张的体重是%f' % 160)
        print('小张的爱好是%s' % '唱歌')
        print('小张的专业是%s' % '计算机信息管理')
        pass
    #函数的调用
    # printInfo() #函数的调用
    # printInfo() #多次调用
    # printInfo()
    # printInfo()
    # printInfo()
    # print('我是其他的代码块...')
    # 进一步的去完善这样的需求【输出不同人的信息】 方案:通过传入参数来解决
    def printInfo(name,height,weight,hobby,pro): #形式参数
        # 函数代码块
        print('%s的身高是%f' %(name,height))
        print('%s的体重是%f' %(name,weight))
        print('%s的爱好是%s' %(name,hobby))
        print('%s的专业是%s' %(name,pro))
        pass
    
    # 调用带参数的信息
    printInfo('小李',189,200,'打游戏','咨询师') #实参
    print('------------------带参数的调用---------------------------')
    printInfo('peter',175,160,'码代码','计算机应用')
    

    注:pass的作用?

  • 参数的分类——必选参数、默认参数【缺省参数】、可选参数、关键字参数

  • 1:必选参数——实际参数和形式参数

  • 形参——sum(a,b)// 不占内存地址

  • 实参——sum(10,20)// 占内存地址

    # 参数的分类:
    # 必选参数、默认参数[缺省参数]、可选参数、关键字参数
    # 参数:其实就是函数为了实现某项特定的功能,进而为了得到实现功能所需要的数据
    # 为了得到外部数据的
    # 1 必选参数
    def sum(a,b): #形式参数:只是意义上的一种参数,在定义的时候是不占内存地址的
        sum=a+b
        print(sum)
        pass
    # 函数调用  在调用的时候必选参数 是必须要赋值的
    sum(20,15) #20 15 实际参数:实参,实实在在的参数,是实际占用内存地址的
    # sum(15) #不能这样写的,
    
  • 2:默认参数/缺省参数

    # 2:默认参数【缺省参数】 始终存在于参数列表中的尾部
    def sum1(a,b=40,c=90):
        print('默认参数使用=%d'%(a+b))
        pass
    # # 默认参数调用
    sum1(10) #在调用的时候如果未赋值,就会用定义函数时给定的默认值
    sum1(2,56)
    
  • 3:可变参数

    #可变参数(当参数的个数不确定时使用,比较灵活
    def getComputer(*args): #可变长的参数
         '''
         计算累加和
        :param args: 可变长的参数类型
         :return:
         '''
         # print(args)
         result=0
         for item in args:
             result+=item
             pass
         print('result=%d'%result)
         pass
    getComputer(1)
    getComputer(1,2)
    getComputer(1,2,3)
    getComputer(1,2,3,4,5,6,7,8)
    
  • 4.关键字可变参数 0-n(字典类型的参数)

    # 关键字可变参数  0-n
    # ** 来定义
    # 在函数体内 参数关键字是一个字典类型 key是一个字符串
    def keyFunc(**kwargs):
        print(kwargs)
        pass
    # 调用
    # keyFunc(1,2,3) 不可以传递的
    dictA={"name":'Leo',"age":35}
    keyFunc(**dictA)
    keyFunc(name='peter',age=26,)
    keyFunc()
    	```
    
    
  • 5.组合参数

    # 组合的使用
    def complexFunc(*args,**kwargs):
         print(args)
         print(kwargs)
         pass
    complexFunc(1,2,3,4,name='刘德华')
    complexFunc(age=36)
    
    # def TestMup(**kwargs,*args): #不符合要求的
         '''
         可选参数必须放到关键字可选参数之前
         可选参数:接受的数据是一个元组类型
         关键字可选参数:接受的数据是一个字段类型
         :param kwargs:
         :param args:
         :return:
         '''
    #     pass
    
  • 函数返回值

    # 函数返回值
    # 概念:函数执行完以后会返回一个对象,如果在函数的内部有return 就可以返回实际的值,否则返回None
    # 类型:可以返回任意类型,返回值类型应该取决于return后面的类型
    # 用途:给调用方返回数据
    # 在一个函数体内可以出现多个return值:但是肯定只能返回一个return
    # 如果在一个函数体内 执行了return,意味着函数就执行完成退出了,return后面的代码语句将不会执行
    def Sum(a,b):
        sum=a+b
        return sum#将计算的结果返回
        pass
    
    # rs=Sum(10,30) #将返回值赋给其他的变量
    # print(rs) #函数的返回值返回到调用的地方
    def calComputer(num):
        li=[]
        result=0
        i=1
        while i<=num:
            result+=i
            i+=1
            pass
        li.append(result)
        return li
        pass
    
    # 调用函数
    value=calComputer(10)
    print(type(value)) #value 类型
    print(value)
    
    def returnTuple():
        '''
        返回元组类型的数据
        :return:
        '''
        # return 1,2,3
        return {"name":"测试"}
        pass
    
    A=returnTuple()
    print(type(A))
    
  • 函数嵌套

    # 函数嵌套
    def fun1():
        print("--------------fun1 start-------------------")
        print("--------------执行代码省略-------------------")
        print("--------------fun1 end-------------------")
        pass
    
    def fun2():
        print("--------------fun2 start-------------------")
        # 调用第一个函数
        fun1()
        print("--------------fun2 end-------------------")
        pass
    
    fun2() #调用函数2
    
    # 函数的分类:根据函数的返回值和函数的参数
    # 有参数无返回值的
    # 有参数又返回值的
    # 无参数又返回值的
    # 无参数无返回值的
    

总结

7.函数(下)

7.1函数的基本类型

7.2全局变量和局部变量

  • ------------局部变量----------------

  • 局部变量 就是在函数内部定义的变量【作用域仅仅局限在函数的内部】

  • 不同的函数 可以定义相同的局部变量,但是各自用各自的 不会产生影响

  • 局部变量的作用:为了临时的保存数据 需要在函数中定义来进行存储

  • ------------全局变量----------------

  • 下面的pro的定义就是一个全局变量【作用域的范围不同】

  • 当全局变量和局部变量出现重复定义的时候,程序会优先执行使用函数内部定义的变量【地头蛇】

  • 如果在函数的内部要想对全局变量进行修改的话,对于不可变类型【str、元组 、number】- #必须使用global 关键字进行声明

  • 注:

    # 以下两个是全部变量
    pro='计算机信息管理'
    name='吴老师'
    def printInfo():
        # name='peter' #局部变量
        print('{}.{}'.format(name,pro))
        pass
    def TestMethod():
        name='刘德华'
        print(name,pro)
        pass
    def changeGlobal():
        '''
        要修改全局变量
        :return:
        '''
        global pro #声明全局变量 后才可以修改
        pro='市场营销' #局部变量
        pass
    
    changeGlobal()
    print(pro) #被修改了吗
    TestMethod()
    printInfo()
    

7.3引用传值


注:这个和java不一样,python是引用传递(记得区分可变类型和不可变类型)。

a=1  #不可变类型
def func(x):
    print('x的地址{}'.format(id(x)))
    x=2
    print('x的值修改之后地址{}'.format(id(x)))
    print(x)
    pass
# 调用函数
# print('a的地址:{}'.format(id(a)))
# func(a)
# print(a)

# 可变类型
# li=[]
# # def testRenc(parms):
# #
# #     li.append([1,3,4,54,67])
# #     print(id(parms))
# #     print('内部的{}'.format(parms))
# #     pass
# #
# # print(id(li))
# # testRenc(li)
# # print('外部的变量对象{}'.format(li))
# 小结
# 1.在python当中  万物皆对象,在函数调用的时候,实参传递的就是对象的引用
# 2.了解了原理之后,就可以更好的去把控 在函数内部的处理是否会影响到函数外部的数据变化
#参数传递是通过对象引用来完成 、参数传递是通过对象引用来完成、参数传递是通过对象引用来完成

7.4匿名函数

  • 语法:

  • lambda 参数1、参数2、参数3:表达式

  • 特点:

  • 7.1使用lambda关键字去创建函数

  • 7.2.没有名字的函数

  • 7.3匿名函数冒号后面的表达式有且只有一个, 注意:是表达式,而不是语句

  • 7.4匿名函数自带return,而这个return的结果就是表达式计算后的结果

  • 缺点:

  • lambde只能是单个表达式,不是一个代码块,lambde的设计就是为了满足简单函数的场景,

  • 仅仅能封装有限的逻辑,复杂逻辑实现不了,必须使用def来处理

    def computer(x,y):
        '''
        计算数据和
        :param x:
        :param y:
        :return:
        '''
        return x+y
        pass
    # 对应的匿名函数
    M=lambda x,y:x+y
    # 通过变量去调用匿名函数
    # print(M(23,19))
    # print(computer(10,45))
    
    result=lambda a,b,c:a*b*c
    # print(result(12,34,2))
    age=25
    
    # print('可以参军' if age>18 else '继续上学') #可以替换传统双分支的写法
    
    # funcTest=lambda x,y:x if x>y else y
    # print(funcTest(2,12))
    
    # rs=(lambda x,y:x if x>y else y)(16,12) #直接的调用
    # print(rs)
    varRs=lambda x:(x**2)+890
    print(varRs(10))
    

7.5递归函数

  • 定义

  • 递归满足的条件

  • 自己调用自己

  • 必须有一个明确的结束条件

  • 优点: 逻辑简单、定义简单

  • 缺点: 容易导致栈溢出,内存资源紧张,甚至内存泄漏

    def jiecheng(n):
        result=1
        for item in range(1,n+1):
            result*=item
            pass
        return result
    
    # print('10的阶乘{}'.format(jiecheng(10)))
    # 递归方式去实现
    def diguiJc(n):
        '''
        递归实现
        :param n: 阶乘参数
        :return:
        '''
        if n==1:
            return 1
        else:
           return n*diguiJc(n-1)
        pass
    
    # 递归调用
    print('5的阶乘{}'.format(diguiJc(5)))
    # 递归案例 模拟实现 树形结构的遍历
    import os #引入文件操作模块
    def findFile(file_Path):
        listRs=os.listdir(file_Path) #得到该路径下所有文件夹
        for fileItem in listRs:
            full_path=os.path.join(file_Path,fileItem) #获取完整的文件路径
            if os.path.isdir(full_path):#判断是否是文件夹
                findFile(full_path) #如果是一个文件夹 再次去递归
            else:
                print(fileItem)
                pass
            pass
        else:
            return
        pass
    
    # 调用搜索文件夹对象
    findFile('E:\\软件')
    

总结

8.内置函数

8.1内置函数功能列表


8.2数学运算

# 取绝对值
# print(abs(-34))
# round  取近似值
# print(round(3.66,1))
# pow 求次方
# print(3**3)
# print(pow(3,3))
# max 求最大值
# print(max([23,123,4,5,2,1,786,234]))
# print(max(23,235))
# sum 使用
# print(sum(range(50),3))
# eval 执行表达式
a,b,c=1,2,3
print('动态执行的函数={}'.format(eval('a*b+c-30')))
def TestFun():
    print('我执行了吗?')
    pass
# eval('TestFun()') #可以调用函数执行
# 类型转换函数
# print(bin(10)) #转换二进制
# print(hex(23)) #十六进制
# 元组转换为列表
tup=(1,2,3,4)
# print(type(tup))
li=list(tup) #强制转换
# print(type(li))
li.append('强制转换成功')
# print(li)
tupList=tuple(li)
# print(type(tupList))

# 字典操作 dict()
# dic=dict(name='小明',age=18) #创建一个字典
# # print(type(dic))
# # # dict['name']='小明'
# # # dict['age']=18
# # print(dic)
# bytes转换
# print(bytes('我喜欢python',encoding='utf-8'))

注:

8.3类型转换运算

8.4序列操作函数

  • all

    # all()  result:bool 对象中的元素除了是 0、空、FALSE 外都算 TRUE, 所有的元素都为True
    # 结果就为True
    print(all([])) #True
    print(all(())) #True
    print(all([1,2,4,False]))#False
    print(all([1,2,4]))#True
    print(all((3,4,0)))#False
    
  • any

    # any  result:bool 类似于逻辑运算符 or的判断,只要有一个元素为True 结果就为True
    print('--------any-------------')
    print(any(('',False,0)))
    print(any((1,2,3)))
    
  • sorted(返回的是一个新的结果,原始对象不会变)

    # sort 和sorted
    li=[2,45,1,67,23,10] #原始对象
    # li.sort() #list的排序方法 直接修改的原始对象
    tupArray=(2,45,1,67,23,10)
    print('--------排序之前---------{}'.format(li))
    varList=sorted(li) #升序排列
    varList=sorted(li,reverse=True) #降序排序
    print('--------排序之后---------{}'.format(varList))
    varRs=sorted(tupArray,reverse=False)
    print(varRs)
    
  • reverse : list.reverse()

  • range

  • zip

    # zip() :就是用来打包的,会把序列中对应的索引位置的元素存储为一个元组
    s1=['a','b','c']
    s2=['你','我','c他','peter']
    s3=['你','我','c他','哈哈','呵呵']
    # print(list(zip(s1))) 压缩一个数据
    zipList=zip(s2,s3) #两个参数
    print(list(zipList))
    def printBookInfo():
        '''
        zip 函数的使用
        :return:
        '''
        books=[] #存储所有的图书信息
        id = input('请输入编号: 每个项以空格分隔')  #str
        bookName = input('请输入书名: 每个项以空格分隔') #str
        bookPos = input('请输入位置: 每个项以空格分隔')
        idList=id.split(' ')
        nameList = bookName.split(' ')
        posList = bookPos.split(' ')
    
        bookInfo=zip(idList,nameList,posList) #打包处理
        for bookItem in bookInfo:
            '''
            遍历图书信息进行存储
            '''
            dictInfo={'编号':bookItem[0],'书名':bookItem[1],'位置':bookItem[2]}
            books.append(dictInfo) #将字典对象添加到list容器中
            pass
        for item in books:
            print(item)
    
    # printBookInfo()
    
  • enumerate

    # enumerate 函数用于将一个可遍历的数据对象
    # (如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,
    # 一般用在 for 循环当中
    
    listObj=['a','b','c']
    for index,item in enumerate(listObj,5):
         print(index,item)
         pass
    dicObj={}
    dicObj['name']='李易峰'
    dicObj['hobby']='唱歌'
    dicObj['pro']='艺术设计'
    # print(dicObj)
    
    for item in enumerate(dicObj):
        print(item)
    

8.5内置函数set

  • 定义:不支持切片和索引,类似字典,但是只有key,是一个无序且不重复的元素集合

  • 创建方式:

    # set 不支持索引和切片,是一个无序的且不重复的容器
    # 类似于字典 但是只有key  没有value
    # 创建集合
    dic1={1:3}
    set1={1,2,3}
    set2={2,3,4}
    print(type(set1)) #集合
    print(type(dic1)) #字典
    # 添加操作
    set1.add('python')
    print(set1)
    # 清空操作
    set1.clear()
    print(set1)
    # 差集操作
    rs=set1.difference(set2)
    print(rs)
    print(set1-set2)
    print(set1)
    # 交集操作
    print(set1.intersection(set2))
    print(set2&set1)
    # 并集操作
    print(set1.union(set2))
    print(set1 | set2)
    # pop 就是从集合中拿数据并且同时删除
    print(set1)
    quData=set1.pop()
    print(quData)
    print(set1)
    print(set1.discard(3)) #指定移除的元素
    print(set1)
    # update 两个集合
    set1.update(set2)
    print(set1)
    

总结


--------------------------------面向对象--------------------------------

1.面向对象(上)

1.1定义

  • 面向对象编程:oop [object oriented programming] 是一种python的编程思路;
  • 面向过程:就是我们一开始学习的,按照解决问题的步骤去写代码 【根据业务逻辑去写代码】,在思考问题的时候, 首先分析’怎么按照步骤去实现’ 然后将问题解决拆解成若干个步骤,并将这些步骤对应成方法一步一步的 最终完成功能。
  • 面向对象:关注的是设计思维【找洗车店 给钱洗车】

1.2类和对象

类和对象

类:类是具有一组 相同或者相似特征【属性】和行为【方法】的一系列[多个]对象组合

现实世界    计算机世界
行为---------> 方法
特征---------->属性

对象: 对象是实实在在的一个东西,类的实例化,具象化

类是对象的抽象化  而对象是类的一个实例

1.3定义类和创建对象、实例方法和属性、init方法

实例方法:在类的内部,使用def 关键字来定义  第一个参数默认是 self
【名字标识可以是其他的名字,但是这个位置必须被占用】

实例方法是归于 类的实例所有

属性:类属性  实例属性
在类的内部定义的变量【类属性】
在方法内部定义的【通过类似于self.变量名】 变量,是实例属性
# 定义类和对象
# 类结构  类名  属性  方法
# class 类名:
#     属性
#     方法

class Person:
    '''
    对应人的特征
    '''
    # name='小明'  #类属性
    age=20       #类属性
    '''
    对应人的行为  实例方法
    '''
    def __init__(self):
        self.name='小明'   #实例属性
        pass
    def eat(parms):
        print("大口的吃饭")
        pass
    def run(self):   #实例方法
        print('飞快的跑')
        pass
    pass
def printInfo():
    '''
    普通方法
    :return:
    '''
    pass
# 创建一个对象【类的实例化】
# 规则格式  对象名=类名()
xm=Person()
xm.eat() #调用函数
xm.run()
print("{}的年龄是:{}".format(xm.name,xm.age))

# 创建另外一个实例对象
xw=Person()
xw.eat()  #实例方法

1.4 init方法

# init传递参数 改进
class Pepole:
    def __init__(self,name,sex,age):
        '''
        实例属性的声明
        '''
        self.name=name
        self.sex=sex
        self.age=age
        pass
    def eat(self,food):
        '''
        吃的行为
        :return:
        '''
        print(self.name+'喜欢吃'+food)
    pass

zp=Pepole('张鹏','男生',18)
print(zp.name,zp.age)
zp.eat('香蕉')
lh=Pepole('李辉','男生',28)
lh.eat('苹果')
print(lh.name,lh.age)

xh=Pepole('小花','女生',20)
xh.eat('橘子')
print(xh.name,xh.age)

# 总结 __init__
# 1. python 自带的内置函数 具有特殊的函数   使用双下划线 包起来的【魔术方法】
# 2. 是一个初始化的方法 用来定义实例属性 和初始化数据的,在创建对象的时候自动调用  不用手动去调用
# 3. 利用传参的机制可以让我们定义功能更加强大并且方便的 类

1.5 self理解

小结  self特点
self只有在类中定义 实例方法的时候才有意义,在调用时候不必传入相应的参数 而是由解释器 自动去指向;![在这里插入图片描述](https://img-blog.csdnimg/6021b15274424412930d9e9cfee67965.png)

self的名字是可以更改的  可以定义成其他的名字,只是约定俗成的定义成了 self
self 指的是 类实例对象本身, 相当于java中 this
class Person:
    def __init__(self,pro,name,food):
        '''

        :param pro: 专业
        :param name: 姓名
        :param food: 食物
        '''
        self.pro=pro  #实例属性的定义
        self.name=name
        self.food=food
        print('----init-----函数执行')
        pass
    '''
   定义类
    '''
    def eat(self,name,food):
        '''
        实例方法
        :return:
        '''
        # print('self=%s',id(self))
        print('%s 喜欢吃 %s 修的专业是:%s'%(self.name,self.food,self.pro))
        pass
 
    pass


# xw是一个新的实例化对象
xw=Person('心理学','小王','榴莲')
# print('xw=%s',id(xw))
# xw.eat('小王','榴莲')
print(xw)  #直接输出对象

1.6 魔术方法

  • 定义:
class Person:
    def __init__(self,pro,name,food):
        '''

        :param pro: 专业
        :param name: 姓名
        :param food: 食物
        '''
        self.pro=pro  #实例属性的定义
        self.name=name
        self.food=food
        print('----init-----函数执行')
        pass
    '''
   定义类
    '''
    def eat(self,name,food):
        '''
        实例方法
        :return:
        '''
        # print('self=%s',id(self))
        print('%s 喜欢吃 %s 修的专业是:%s'%(self.name,self.food,self.pro))
        pass
    def __str__(self):
        '''
        打印对象 自定义对象 是内容格式的
        :return:
        '''
        return '%s 喜欢吃 %s 修的专业是:%s'%(self.name,self.food,self.pro)
        pass
    def __new__(cls, *args, **kwargs):
        '''
        创建对象实例的方法  每调用一次 就会生成一个新的对象 cls 就是class的缩写

        场景:可以控制创建对象的一些属性限定 经常用来做单例模式的时候来使用
        :param args:
        :param kwargs:
        '''
        print('----new-----函数的执行')
        return object.__new__(cls) #在这里是真正创建对象实例的
        pass
    pass


# xw是一个新的实例化对象
xw=Person('心理学','小王','榴莲')
# print('xw=%s',id(xw))
# xw.eat('小王','榴莲')
print(xw)  #直接输出对象
# 小结  self特点
# self只有在类中定义 实例方法的时候才有意义,在调用时候不必传入相应的参数 而是由解释器 自动去指向
# self的名字是可以更改的  可以定义成其他的名字,只是约定俗成的定义成了 self
# self 指的是 类实例对象本身, 相当于java中 this

# __new__和__init___函数的区别
# __new__ 类的实例化方法 必须要返回该实例 否则对象就创建不成功
# __init___ 用来做数据属性的初始化工作  也可以认为是实例的构造方法  接受类的实例 self 并对其进行构造
# __new__   至少有一个参数是 cls 代表要实例化的类 ,此参数在实例化时由python解释器自动提供
# __new__  函数 执行要早于 __init___ 函数

2.面向对象(中)

2.1析构方法

class Animal:
    def __init__(self,name):
        self.name=name
        print('这是构造初始化方法')
        pass
    def __del__(self):
        # 主要的应用就是来操作 对象的释放  一旦释放完毕  对象便不能在使用
        print('当在某个作用域下面 没有被使用【引用】的情况下 解析器会自动的调用此函数 来释放内存空间')
        print('这是析构方法')
        print('%s 这个对象 被彻底清理了 内存空间也释放了'%self.name)
    pass

cat=Animal('小花猫')
# del cat  #手动的去清理删除对象  会指定__del__函数
print(cat.name)
input('程序等待中.....')
# print('*'*40)
# dog=Animal('柯基小狗')

2.2单继承

class Animal:
    def  eat(self):
        '''
        吃
        :return:
        '''
        print('吃饭了')
        pass
    def drink(self):
        '''
        喝
        :return:
        '''
        pass

class Dog(Animal): #继承了Animal 父类 此时dog就是子类
    def wwj(self):
        '''
        子类独有的实现
        :return:
        '''
        print('小狗汪汪叫')
    pass
class Cat(Animal):
    def mmj(self):
        '''
         子类独有的实现
        :return:
        '''
        print('小猫喵喵叫')
    pass

d1=Dog()
d1.eat() #具备了吃的行为  是继承了父类的行为
d1.wwj()
print('**************cat 的行为**********************')
c1=Cat()
c1.eat()
c1.mmj()

2.3多继承

注:# 问题是 当多个父类当中存在相同方法的时候 应该去调用哪一个呢?
答:广度优先/(print(A.mro) #可以显示类的依次继承关系)

class shenxian:
    def fly(self):
        print("神仙都会飞")
    pass
class Monkey:
    def chitao(self):
        print('猴子喜欢吃桃')
    pass
class Sunwukong(shenxian,Monkey): #即使神仙  同时也是猴子
    pass

# swk=Sunwukong()
# swk.chitao()
# swk.fly()
####################################################
# 问题是  当多个父类当中存在相同方法的时候  应该去调用哪一个呢
class D(object):
    def eat(self):
        print('D.eat')
        pass
    pass
class C(D):
    def eat(self):
        print('C.eat')
        pass
    pass
class B(D):
    pass
class A(B,C):
    pass
a=A()
a.eat()
print(A.__mro__) #可以显示类的依次继承关系
#在执行eat的方法时 查找方法的顺序是
# 首先到A里面去查找  如果A中没有 则继续的去B类中去查找 如果B中没有
# 则去C中查找 如果C类中没有 则去D类中去查找,如果还是没有找到 就会报错
# A-B-C-D  也是继承的顺序

2.4间接继承

class GrandFather:
    def eat(self):
        print('吃的 方法')
        pass
    pass
class Father(GrandFather):
    pass

class Son(Father):
    pass

son=Son()
print(Son.__mro__)
son.eat() #此方法 是从GrandFather继承过来的

2.5重写和调用父类方法

  • 所谓重写,就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法
  • 为什么要重写, 父类的方法已经不满足子类的需要,那么子类就可以重写父类或者完善父类的方法

class Dog:
    def __init__(self,name,color):
        self.name=name
        self.color=color

    def bark(self):
        print('汪汪叫....')
        pass
    pass
class kejiquan(Dog):
    def __init__(self,name,color):#属于重写父类的方法
        # 针对这种需求  我们就需要去调用父类的函数了
        # Dog.__init__(self,name,color) #手动调用  调用父类的方法了 执行完毕就可以具备name,color这两个实例属性了\
        super().__init__(name,color) #super是自动找到父类 进而调用方法, 假设继承了多个父类,那么会按照顺序逐个去找 然后在调用
        # 拓展其他的属性
        self.height=90
        self.weight=20
        pass
    def __str__(self):
        return '{}的颜色会{} 它的身高是{}cm 体重是:{}'.format(self.name,self.color,self.height,self.weight
                                                  )
    def bark(self): #属于重写类的方法
        super().bark() #调用父类的方法
        print('叫的跟神一样')
        print(self.name)
    pass

kj=kejiquan('柯基犬','红色')
kj.bark()
print(kj)

注: super是自动找到父类 进而调用方法

2.6 类属性和实例属性

注: 类属性 就是类对象所拥有的属性(类对象不同于实例对象,这里和java有点不同,这里所说的类对象应该就是java里面的元对象)

  • 小结
  • 类属性是可以 被类对象和实例对象共同访问使用的
  • 实例属性只能由实例对象所访问
class Student:
    name='李明' #属于类属性  就是student类对象所拥有的
    def __init__(self,age):
        self.age=age #实例属性
        pass
    @staticmethod
    def aaa(x,y):
        print(x+y)
    pass

Student.name='李易峰' #通过类对象去修改数据 可以修改的  因为name的所拥有的权利属于类对象

lm=Student(18)
print(lm.name) #通过实例对象去访问类属性
# lm.name='刘德华'  #通过实例对象 对类属性进行修改 可以吗? 不可以的
print(lm.name)
print(lm.age)
Student.aaa(4,6)
print('---------xh的数据---------------')
xh=Student(28)
print(xh.name)
print(xh.age)
print('---------通过类对象 student 去访问name---------------')
# print(Student.name)  如 类名.属性名 形式去访问
# print(Student.age)
# 小结
# 类属性是可以 被类对象和实例对象共同访问使用的
# 实例属性只能由实例对象所访问

分析:

2.7类方法和静态方法

  • 类方法是类所拥有的,可以访问类变量,可以通过类对象和实例对象访问。必须传参数。
  • 静态方法和类方法差不多,但是不必须传参数。
  • 为什么要使用静态方法呢?1. 由于静态方法主要来存放逻辑性的代码,本身和类以及实例对象没有交互;2.也就是说,在静态方法中,不会涉及到类中方法和属性的操作;3.数据资源能够得到有效的充分利用。
class  People:
    country='china'
    #类方法 用 classmethod 来进行修饰
    @classmethod
    def get_country(cls):
        return cls.country #访问类属性
        pass
    @classmethod
    def change_country(cls,data):
        cls.country=data #修改类属性的值  在类方法中
        pass
    @staticmethod
    def getData():
        return People.country  #通过类对象去引用
        pass
    @staticmethod
    def add(x,y):
        return x+y
        pass


print(People.add(10,56)) #带有参数的静态方法

# print(People.getData())

# print(People.get_country()) #通过类对象去引用
p=People()
print(p.getData()) #注意 一般情况下 我们不会通过实例对象去访问静态方法
# print('实例对象访问 %s'%p.get_country())
# print('-----------------修改之后---------------------------')
# People.change_country('英国')
# print(People.get_country()) #通过类对象去引用

# 为什么要使用静态方法呢
# 由于静态方法主要来存放逻辑性的代码,本身和类以及实例对象没有交互,
# 也就是说,在静态方法中,不会涉及到类中方法和属性的操作
# 数据资源能够得到有效的充分利用

# demo  返回当前的系统时间
import  time # 引入第三方的时间模块
class TimeTest:
    def __init__(self,hour,min,second):
        self.hour=hour
        self.min = min
        self.second = second

    @staticmethod
    def showTime():
        return time.strftime("%H:%M:%S",time.localtime())
        pass
    pass

print(TimeTest.showTime())
t=TimeTest(2,10,15)
print(t.showTime()) #没有必要通过这种方式去访问 静态方法

2.8三种方法对比

  • 从方法定义的形式可以看出来
  • 1.类方法的第一个参数是类对象 cls 进而去引用类对象的属性和方法 必须用装饰器 @classmethod来修饰
  • 2.实例方法的第一个参数必须是self,通过这个self 可以去引用类属性或者实例属性,若存在相同名称实例属性和类属性的话,实例属性的优先级最高
  • 3.静态方法不需要定义额外的参数,若是要引用属性的话 则可以通过类对象或者是实例对象去引用即可 必须用装饰器 @staticmethod来修饰

2.9多态

  • 多态:顾名思义就是多种状态、形态,就是同一种行为 对于不同的子类【对象】有不同的行为表现

  • 要想实现多态 必须的有两个前提需要遵守:

  • 1、继承:多态必须发生在父类和子类之间

  • 2、重写: 子类重写父类的方法

  • 多态有什么用: 增加程序的灵活性;增加程序的拓展性。

# 案例演示
class Animal:
    '''
    父类【基类】
    '''
    def say_who(self):
        print('我是一个动物....')
        pass
    pass
class Duck(Animal):
    '''
      鸭子类 【子类】 派生类
    '''
    def say_who(self):
        '''
        在这里重写父类的方法
        :return:
        '''
        print('我是一只漂亮的鸭子')
        pass
    pass
class Dog(Animal):
    '''
     小狗类 【子类】 派生类
    '''
    def say_who(self):
        print('我是一只哈巴狗')
        pass
    pass

class Cat(Animal):
    '''
        小猫类 【子类】 派生类
    '''
    def say_who(self):
        print('我是一只小花猫 喵喵喵喵')
        pass
    pass


class Bird(Animal):
    '''
    新增鸟类 无需修改原来的代码
    '''
    def say_who(self):
        print('我是一只黄鹂鸟')
    pass

class People:
    def say_who(self):
        print('我是人类')
    pass


class student(People):
    def say_who(self):
        print('我是一年级的学习 张明')
    pass

def commonInvoke(obj):
    '''
    统一调用的方法
    :param obj: 对象的实例
    :return:
    '''
    obj.say_who()

# duck1=Duck()
# duck1.say_who()
# dog1=Dog()
# dog1.say_who()
# cat1=Cat()
# cat1.say_who()

listObj=[Duck(), Dog(),Cat(),Bird(),student()]
for item in listObj:
    '''
     循环去调用函数
    '''
    commonInvoke(item)



2.10 三大特征(面向对象)

  • 在python中展现面向对象的三大特征:

  • 封装、继承、多态

  • 封装:指的是把内容封装到某个地方,便于后面的使用
    他需要:
    把内容封装到某个地方
    从另外一个地方去调用被封装的内容
    对于封装来说 其实就是使用初始化构造方法将内容封装到对象中,然后通过对象直接或者self来获取被封装的内容

  • 继承: 和现实生活当中的继承是一样的:也就是 子可以继承父的内容【属性和行为】(爸爸有的儿子都有,相反 儿子有的爸爸不一定有)
    所以对于面向对象的继承来说 其实就是将多个类共有的方法提取到父类中 子类仅需继承父类而不必一一去实现
    这样就可以极大的提高效率 减少代码的重复编写,精简代码的层级结构 便于拓展

     class 类名(父类):
          '''
           子类就可以继承父类中公共的属性和方法
          '''
     	pass
    
  • 多态:顾名思义就是多种状态、形态,就是同一种行为 对于不同的子类【对象】有不同的行为表现
    要想实现多态 必须的有两个前提需要遵守:
    1、继承:多态必须发生在父类和子类之间
    2、重写: 子类重写父类的方法

3.面向对象(下)

3.1私有化属性

  • 使用私有属性的场景
  • 1.把特定的一个属性隐藏起来 不想让类的外部进行直接调用
  • 2.我想保护这个属性 不想让属性的值随意的改变
  • 3.保护这个属性 不想让派生类【子类】去继承

class Person:
    __hobby='跳舞'  #私有的类属性
    def __init__(self):
        self.__name='李四' #加两个下划线 将此属性私有化之后  就不能再外部直接访问了,当然在类的内部是可以防蚊贴
        self.age=30
        pass
    def __str__(self):
        '''
        私有化的属性在内部可以使用 self.__name
        :return:
        '''
        return '{}的年龄是{} 爱好是{}'.format(self.__name,self.age,Person.__hobby)
    def  changeValue(self):
        Person.__hobby='唱歌'
class Student(Person):
    def printInfo(self):
        # print(self.__name)  #在此访问父类中的私有属性 可以吗?   不可以
        print(self.age)
    pass


stu=Student()
# print(stu.__name)
stu.printInfo()
stu.changeValue() #修改私有属性的值
print(stu)
# print(stu.__hobby) #实例对象访问类属性
# print(Person.__hobby) #实例对象访问类属性

# xl=Person()
# # print(xl.__name) #是通过类对象 在外部访问的 不能访问私有属性
# print(xl)

# 小结:
# 1 私有化的【实例】属性 不能再外部直接的访问  可以在类的内部随意的使用
# 2.子类不能继承父类的私有化属性【只能继承父类公共的属性和行为】
# 3. 在属性名的前面直接加‘ __’  就可以变为私有化了

3.2私有化方法

class Animal:
    def __eat(self):
        print('吃东西')
        pass
    def run(self):
        self.__eat() #在此调用私有化的方法
        print('飞快的跑')
    pass

class Bird(Animal):
    pass

b1=Bird()
# print(b1.eat())
# b1.eat()
b1.run()

3.3Property属性函数(意义不大)

  • 目的:不需要通过函数的形式,来访问私有属性
class Person(object):
    def __init__(self):
        self.__age = 18 # 定义一个私有化属性,属性名字前加连个 __ 下滑线
    # 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)
    # 实现方式2  通过装饰器的方式去声明
    @property  #用装饰器修饰 添加属性标志  提供一个getter方法
    def age(self):
        return self.__age
    @age.setter   #提供一个setter方法
    def age(self,parms):
        if parms < 0:
            print('年龄不能小于0')
        else:
            self.__age=parms
            pass
        pass


    pass
p1=Person()
print(p1.age)
p1.age=30
print(p1.age)
# p1.get_age()
# p1.set_age()


3.4__new__方法

class Animal:
    def __init__(self):
        self.color='红色'
        pass
    #在python当中, 如果不重写 __new__ 默认结构如下
    def __new__(cls, *args, **kwargs):
        return super().__new__(cls,*args, **kwargs)
        # return object.__new__(cls, *args, **kwargs)
    pass

tigger=Animal() #实例化的过程会自动调用__new__去创建实例
# 在新式类中 __new__  才是真正的实例化的方法,为类提供外壳制造出实例框架,然后调用该框架内的构造方法__init__ 进行丰满操作
# 比喻建房子 __new__   方法负责开发地皮 打地基 并将原料存放在工地,而__init__ 负责从工地取材料建造出地皮开发图纸规定的大楼,
# 负责细节设计、建造 最终完成

3.5单例模式

  • 单例模式 是一种常用的软件设计模式 目的:确保某一个类只有一个实例存在
  • 如果希望在真个系统中 某个类只能出现一个实例的时候,那么这个单例对象就满足要求
  • 创建一个单例对象 基于__new__去实现的【推荐的一种】

class DataBaseClass(object):
    def __new__(cls, *args, **kwargs):
        # cls._instance=cls.__new__(cls)  不能使用自身的new方法
            # 容易造成一个深度递归,应该调用父类的new方法
        if not hasattr(cls,'_instance'):  #如果不存在就开始创建
            cls._instance=super().__new__(cls,*args, **kwargs)
        return cls._instance
    pass

class DBoptSingle(DataBaseClass):
    pass

db1=DBoptSingle()
print(id(db1))
db2=DBoptSingle()
print(id(db2))
db3=DBoptSingle()
print(id(db3))

------------------------------------异常处理--------------------------------------

1.异常处理(1)

  • 语法格式
# import Exception
# except 在捕获错误异常的时候  只要根据具体的错误类型来捕获的
# 用一个块 可以捕获多个不同类型的异常
# Exception 可以捕获所有的异常  当对出现的问题或者错误不确定的情况下  可以使用Exception
# print(dir(Exception))
try:
    # print(b) #捕获逻辑的代码
    li=[1,2,34]
    print(li[10])  #通过下标去访问列表
    # a=10/0
    pass
except  NameError as msg:
#     # 捕获到的错误 才会在这里执行
#     print(msg)
     pass
except IndexError as msg:
#     print(msg)
     pass
except ZeroDivisionError as msg:
#     print(msg)
    pass
except Exception as result:
    # print(result)
    # 在此尽量的去处理捕获到的错误
    pass
# print('初次接触异常处理')
# print('HAHAHAHHAHA')

# try-except-else

# try:
#     print('我是没有错误产生的')
#     pass
# except SyntaxError as msg:
#     print(msg)
# except Exception as msg:
#     print('error',msg)
# else:
#     print('当Try里面的代码 没有出现异常的情况下 我才会执行')
#     pass

# try-except-finally
try:
    int('34')
    open('aaaa.txt')
except Exception as msg:
    print(msg)
    pass
finally:
    print('释放文件的资源、数据库连接是资源等等')
    print('不管有没有出错都执行的代码块')

2.异常处理(2)

  • 常见的异常类型
    异常	        导致的错误
    AssertionError	当assert语句失败时引发。
    AttributeError	当属性分配或引用失败时引发。
    EOFError	当input()函数达到文件结束条件时引发。
    FloatingPointError	当浮点运算失败时引发。
    GeneratorExit	调用生成器的close()方法时引发。
    ImportError	找不到导入的模块时引发。
    IndexError	当序列的索引超出范围时引发。
    KeyError	在字典中找不到键时引发。
    KeyboardInterrupt	当用户按下中断键(Ctrl+c或delete)时引发。
    MemoryError	当操作耗尽内存时引发。
    NameError	在局部或全局范围内找不到变量时引发。
    NotImplementedError	由抽象方法提出。
    OSError	当系统操作导致系统相关错误时引发。
    OverflowError	当算术运算的结果太大而无法表示时引发。
    ReferenceError	使用弱引用代理访问垃圾收集的引用时引发。
    RuntimeError	当错误不属于任何其他类别时引发。
    StopIteration	函数引发,以指示迭代器不再返回任何项。
    SyntaxError	遇到语法错误时由解析器引发。
    IndentationError	当缩进不正确时引发。
    TabError	当缩进由不一致的制表符和空格组成时引发。
    SystemError	当解释器检测到内部错误时引发。
    SystemExit	由sys.exit()函数引发。
    TypeError	将函数或操作应用于类型不正确的对象时引发。
    UnboundLocalError	当在函数或方法中引用局部变量,但没有将值绑定到该变量时引发。
    UnicodeError	当发生与unicode相关的编码或解码错误时引发。
    UnicodeEncodeError	当编码过程中发生与unicode相关的错误时引发。
    UnicodeDecodeError	当解码过程中出现与unicode相关的错误时引发。
    UnicodeTranslateError	翻译过程中发生与unicode相关的错误时引发。
    ValueError	当函数得到类型正确但值不正确的参数时引发。
    ZeroDivisionError	当除法或模运算的第二个操作数为零时引发。
    
  • 异常处理机制
    
    def A(s):
        return 10/int(s)
        pass
    def B(s):
        return A(s)*2
    def main():
        # B(0)
        try:
            B('0')
            pass
        except Exception as msg:
            print(msg)
            pass
        pass
    
    # main()
    # 不需要在每个可能出错的地方去捕获,只要在合适的层次去捕获错误就可以了 这样的话 就大大减少我们写try---except的麻烦
    # 异常的抛出机制
    #如果在运行时发生异常  解释器会查找相应的异常捕获类型
    #如果在当前函数里面没有找到的话  它会将异常传递给上层的调用函数,看能否处理
    # 如果在最外层 没有找到的话,解释器就会退出 程序down哦
    

3.异常处理(3)

  • 自定义异常:都要直接或者间接继承Error或者Exception类

    class ToolongMyException(Exception):
        def __init__(self,leng):
            '''
    
            :param leng: 长度
            '''
            self.len=leng
            pass
        def __str__(self):
            return '您输入姓名数据长度是'+str(self.len)+'超过长度了..'
        pass
    
    def name_Test():
        name=input('请输入姓名.....')
        try:
            if  len(name)>5:
                raise ToolongMyException(len(name))
            else:
                print(name)
                pass
            pass
        except ToolongMyException as result:
            print(result)
            pass
        finally:
            print('执行完毕了....')
    
    name_Test()
    
    

4.动态添加属性和方法(了解)

  • 代码

    import types  #添加方法的库
    
    def dymicMethod(self):
        print('{}的体重是:{}kg 在 {} 读大学'.format(self.name,self.weight,Student.shcool))
        pass
    @classmethod
    def classTest(cls):
        print('这是一个类方法')
        pass
    
    @staticmethod
    def staticMethodTest():
        print('这是一个静态方法')
        pass
    
    class Student:
        def __init__(self,name,age):
            self.name=name
            self.age=age
        pass
        def __str__(self):
            return '{}今天{}岁了'.format(self.name,self.age)
        pass
    
    print('绑定类方法')
    Student.TestMethod=classTest
    # Student.TestMethod()
    
    Student.staticMethodTest=staticMethodTest
    Student.staticMethodTest()
    
    
    print('---------------绑定类方法执行结束----------------------')
    
    zyh=Student('张艳华',20)
    zyh.weight=50 #动态添加
    zyh.printInfo=types.MethodType(dymicMethod,zyh) #动态的绑定方法
    
    zyh.TestMethod()
    print('-------------实例对象调用 动态绑定类方法-----------------------')
    # print(zyh)
    # print(zyh.weight)
    print('-------------另外一个实例对象  张明--------------------------')
    zm=Student('张名',20)
    zm.weight=80 #动态添加
    print(zm)
    
    zm.printInfo=types.MethodType(dymicMethod,zm) #动态的绑定方法
    # print(zm.weight)
    print('-------------给类对象添加属性--------------------------')
    Student.shcool='北京邮电大学' #动态添加类属性
    print(zm.shcool)
    print('-------------执行动态调用实例方法--------------------------')
    zyh.printInfo() #调用动态绑定的方法
    zm.printInfo()
    


5. __slots __属性

  • 作用: 限制要添加的实例属性;节约内存空间
    
    class Student(object):
        __slots__ = ('name','age')
        def __str__(self):
            return '{}....{}'.format(self.name,self.age)
        pass
    xw=Student()
    xw.name='小王'
    xw.age=20
    xw.score=96 # 没有在范围内 所以报错
    # print(xw.__dict__) #所有可以用的属性都在这里存储  不足的地方就是占用的内存空间大
    # 可以看到 在定义了 slots变量之后 student类的实例已经不能随意创建不在 __slots__定义的属性了
    # 同时还可以看到实例当中也不在有__dict__
    # print(xw)
    
    # 在继承关系当中的使用  __slots__
    # 子类未声明  __slots__时,那么是不会继承父类的__slots__,此时子类是可以随意的属性赋值的
    # 子类声明 了__slots__时,继承父类的__slots__,也就是子类__slots__的范围是为:
    # 其自身+父类的__slots__
    class subStudent(Student):
        __slots__ = ('gender','pro')
        pass
    ln=subStudent()
    ln.gender='男'
    ln.pro='计算机信息管理'
    print(ln.gender,ln.pro)
    

6.文件操作

6.1文件读写

  • # 文件的操作
    # 打开文件 open
    # 默认的编码是gbk 这个是中文编码,最好的习惯呢就是我们再打开一个文件的时候
    # 给它指定一个编码类型
    fobj = open('./Test.txt','w',encoding='utf-8')
    # # 开始操作 读/写操作
    fobj.write('在苍茫的大海上')
    fobj.write('狂风卷积着乌云')
    fobj.write('在乌云和大海之间\r\n')
    fobj.write('海燕像黑色的闪电\r\n')
    fobj.close()
    # 以二进制的形式去写数据
    fobj=open('Test_1.txt','wb') #str-->bytes
    fobj.write('在乌云和大海之间'.encode('utf-8'))
    fobj.close()
    #用于追加数据
    fobj=open('Test.txt','a') 
    fobj.write('在乌云和大海之间\r\n')
    fobj.write('海燕像黑色的闪电\r\n')
    fobj.close()
    fobj=open('Test.txt','a') #  a  用于追加数据
    fobj.write('在苍茫的大海上')
    fobj.write('狂风卷积着乌云')
    fobj.write('在乌云和大海之间\n')
    fobj.write('海燕像黑色的闪电\n')
    fobj.write('今天我诗兴大发\n')
    fobj.write('发感觉咋样呢\n')
    fobj.close()
    
  • # 读数据操作
    f=open('Test.txt','rb')
    data=f.read() #读取所有的数据
    print(data)
    print(data.decode('gbk'))
    # print(f.read(12))
    # # print(f.read())
    # print(f.readline()) #读一行数据
    # print(f.readlines(1))
    # f.close()  #文件对象关闭掉
    
    # with上下文管理对象
    # 优点 自动释放打开关联的对象
    with open('Test.txt','a') as f:
        # print(f.read())
        f.write('我觉得python非常的好学\n')
    
    
    # 小结
    # 文件读写的几种操作方式
    # read  r r+  rb  rb+
    # r r+ 只读  使用普通读取场景
    # rb  rb+  适用于 文件 图片 视频 音频 这样文件读取
    # write w  w+ wb+  wb a  ab
    # w wb+ w+  每次都会去创建文件
    # 二进制读写的时候 要注意编码问题  默认情况下 我们写入文件的编码是gbk
    # a  ab a+  在原有的文件的基础之后去【文件指针的末尾】去追加,
    # 并不会每次的都去创建一个新的文件
    
    def ctime(sec):
        pass
    
    

注:模式

6.2备份文件

# import fileOpt

# 文件的备份
def copyFile():
    # 接收用户输入的文件名
    old_file=input('请输入要备份的文件名:')
    file_list=old_file.split('.')
    # 构造新的文件名.加上备份的后缀
    new_file=file_list[0]+'_备份.'+file_list[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

copyFile()


def copyBigFile():
    # 接收用户输入的文件名
    old_file=input('请输入要备份的文件名:')
    file_list=old_file.split('.')
    # 构造新的文件名.加上备份的后缀
    new_file=file_list[0]+'_备份.'+file_list[1]
    try:
        #监视啊哟处理的逻辑
        with open(old_file,'r') as old_f,open(new_file,'w')as new_f:
            while True:
                content=old_f.read(1024) #一次读取1024字符
                new_f.write(content)
                if len(content)<1024:
                    break
    except  Exception as msg:
        print(msg)
    pass

6.3文件定位(了解)

# tell  返回指针当前所在的位置
# 对于中文讲 每次读取到的一个汉字 实际上占用了 2个字符
with open('Test.txt','r+') as f:
    print(f.read(3))
    print(f.tell())
    print(f.read(2))
    print(f.tell())
   pass

truncate 可以对源文件进行截取操作
fobjB=open('Test.txt','r')
print(fobjB.read())
fobjB.close()
print('截取之后的数据........')

fobjA=open('Test.txt','r+')
fobjA.truncate(15) #保留前15个字符
print(fobjA.read())
fobjA.close()

# seek 可以控制光标所在位置
with open('Test_备份.txt','rb') as f:
    f.seek(4,0) #光标是从0的位置开始 像前【右】移动 4个字符
    data=f.read(2)
    print(data.decode('gbk'))
    f.seek(-2,1) #相当于光标有设置到了0的位置
    print(f.read(4).decode('gbk'))
    f.seek(-6,2) #2 表示光标在末尾处  往回移动了6个字符
    print(f.read(4).decode('gbk'))
    pass

# 对于这种情况 用'r'这种模式打开文件,在文本文件中,没有使用二进制的选项打开文件,
# 只允许从文件的开头计算相对位置,从文件尾部计算或者当前计算的话 就会引发异常

6.4模块导入

  • 1:import 模块
    注: import 到首次导入模块的时候 会发生如下3步操作:
    1 打开模块文件
    2 执行模块对应的文件,将执行过程中产生的名字都丢到模块的名称空间
    3 在程序中会有一个模块【可以取别名的】的名称指向模块的名称空间去

    import time as myTime  #加了一个别名
    print(myTime.ctime())
    # print(time.ctime()) #调用模块中的函数了
    import fileOpt
    
  • 2:路径搜索过程

  • 3:from 模块 import 方法
    注:from …import 首次导入发生了3个步骤
    1 以模块为准创造一个模块的名称空间
    2 执行模块对应的文件了,将执行过程中产生的名字都丢到模块的名称空间
    3 在当前执行文件的名称空间中拿到一个名字,该名字直接指向模块中的某一个名字,意味着可以不用加任何的前缀而直接使用

    from time import ctime,time #部分导入
    # from time import *
    print(ctime())
    
    # 优点:不用加前缀 代码更加简洁了
    # 缺点: 容易与当前执行文件中名称空间中的名字冲突
    
  • 4.比较

    	# 相同点和不同点
    	# 相同
    	# 都会执行模块对应的文件 并且呢 都会产生模块课的名称空间
    	# 两者在调用功能时呢,都需要转到定义时寻找作用域关系
    	# 不同点
    	# import 需要加前缀  from...import 不需要加前缀
    

7.常见模块

  • os模块

  • time、datatime模块

8.模块的制作、发布、安装

8.1模块的制作

  • 模块的制作
  • 一个随便的py文件就是一个模块
  • 有了__name__,这样别的模块调用的时候,不会运行

    注:__all__的作用

8.2模块的发布

  • 1.写好包放在一个目录下
  • 2.创建setup.py文件
  • 3.创建模块
  • 4.生成压缩包
  • 5.tree看结构

8.3模块的安装

  • 1.压缩包解压
  • 2.安装
  • 3.模块引入

------------------------------------内存管理---------------------------------

1.引用计数法


注:类似于java,这个系统自动回收垃圾对象,明显有循环引用的弊端。

  • 代码例子
    import sys
    import psutil
    import os
    import gc
    
    print(gc.get_threshold())
    def showMemSize(tag):
        pid=os.getpid()
        p=psutil.Process(pid)
        info=p.memory_full_info()
        memory=info.uss/1024/1024
        print('{} memory used:{} MB'.format(tag,memory))
        pass
    
    # 验证循环引用的情况
    def func():
        showMemSize('初始化')
        a=[i for i in range(10000000)]
        b=[i for i in range(10000000)]
        a.append(b)
        b.append(a)
        showMemSize('创建列表对象 a b 之后')
        # print(sys.getrefcount(a))
        # print(sys.getrefcount(b))
        # del a
        # del b
        pass
    
    func()
    gc.collect() #手动是释放的
    showMemSize('完成时候的')
    # sys.getrefcount()
    # a=[]
    # print(sys.getrefcount(a)) #两次
    # b=a
    # print(sys.getrefcount(a)) #三次
    # c=b
    # d=b
    # e=c
    # f=e
    # g=d
    # print(sys.getrefcount(a)) #八次
    

2.标记清除、分代收集算法

  • 标记清楚:先标记对象,然后清除垃圾(java的可达性分析)

3.小整数和大整数对象池(内存优化)

  • 类似于java的字符串常量池
  • 大整数池和小整数池的区别是:
    1 从结果来看是一样的
    2 大整数池是没有提前的创建好对象,是个空池子,需要我们自己去创建,创建好之后,会把整数对象保存到池子里面,后面都不需要再创建了 直接拿来使用;小整数池是提前将【-5,256】的数据都提前创建好; 字符串的驻留共享机制intern机制
    a=140
    b=140
    print(id(a))
    print(id(a))
    # del a
    # del b
    # c=140
    # print(id(c))
    # biga=100000
    # bigb=100000
    # print(id(biga))
    # print(id(bigb))
    # del biga
    # del bigb
    # bigc=100000
    # print(id(bigc))
    # sa='ab_c'
    # sb='ab_c'
    # sc='ab_c'
    # sd='ab_c'
    

4.规范

  • 缩进:4个空格的缩进
  • 添加注释
  • 命名规范:类–大驼峰法,方法–小驼峰法

5.命令行参数_sys

  • sys模块

    import sys
    import argparse
    print('参数个数为:', len(sys.argv), '个参数.')
    print('参数列表:', str(sys.argv[1:]))
    
  • 执行结果

  • 弊端:

6.命令行参数_argparse

  • argparse为首选

    # 创建一个解析器对象
    parse=argparse.ArgumentParser(prog='my - 我自己的程序', usage='%(prog)s [options] usage',
                                  description = 'my-编写自定义命令行的文件',epilog = 'my - epilog')
    
    # 添加位置参数【必选参数】
    parse.add_argument('name',type=str, help='你自己的名字')
    parse.add_argument('age',type=str,help='你的年龄')
    
    # 添加可选参数
    # parse.add_argument('-s','--sex', action='append',type=str,help='你的性别')
    # 限定一个范围
    parse.add_argument('-s','--sex',default='男', choices=['男','femal','女','male'],type=str,help='你的性别')
    # print(parse.print_help())
    
    result=parse.parse_args() #开始解析参数
    print(result.name,result.age,result.sex)
    
  • 构造对象的参数说明

  • 参数的属性

    参考链接:
    https://www.bilibili/video/BV1vA411b7Rn?p=24

更多推荐

python学习(总)