陈佳浩
陈佳浩
发布于 2024-06-26 / 40 阅读
0
0

Python学习

  • Python学习
  • Python
    • 输出函数print
    • 转义字符
    • 保留字、标识符
      • 查看python的保留字
      • 规则
    • 变量
    • 数据类型
    • 注释
    • 输入函数input
    • 计算
      • 运算符
        • 算数运算符
        • 赋值运算符
        • 比较运算符
        • 布尔值运算
        • 位运算
        • 运算符优先级
    • 流程控制
      • if判断
      • 第二种写法(if else)
      • 嵌套if
      • pass语句
      • range函数
      • while循环
      • for-in循环
      • break语句
      • continue语句
      • else语句
      • 嵌套循环
    • 列表
      • 创建列表的两种方式
      • 取值
      • 切片
      • 取索引
      • 列表元素查询
        • 判断元素是否存在于列表中
        • 列表元素遍历
      • 列表元素的增删改
        • 列表元素的增加操作
        • 列表元素的删除操作
        • 列表元素的修改操作
        • 列表元素的排序操作
        • 列表生成式
    • 字典
      • 字典的创建
        • 使用花括号
        • 使用dict
        • 创建空字典
      • 元素获取
      • key的判断
      • 字典元素的增删
      • 获取字典视图
      • 字典元素的遍历
      • 字典生成式
    • 元组
      • 元组创建方式
      • 元组的遍历
    • 集合
      • 集合的创建方式
      • 集合的相关操作
      • 集合间的关系
      • 集合的数学操作
      • 集合生成式
    • 字符串
      • 字符串查询操作的方法
      • 字符串判断
      • 字符串查找&计数&修改&替换
      • 字符串内容对齐操作的方法
      • 字符串劈分操作的方法
      • 判断字符串操作的方法
      • 字符串操作的其他方法
        • 字符串的替换
        • 字符串的合并
      • 字符串的比较操作
      • 字符串的切片操作
      • 格式化字符串
      • 格式化输出方法
    • 函数
      • 函数的创建和调用
      • 函数的参数传递
      • 函数的返回值
      • 函数的参数定义
      • 变量的作用域
      • 递归函数
      • map函数
      • reduce函数
      • sum函数
    • Bug
      • Bug的常见类型
      • Python的异常处理机制
        • traceback模块
      • raise使用
      • 开发环境的调试
      • 练习
    • 编程思想
    • 类与对象
      • 类与对象
      • 类与实例及访问限制
      • 继承和多态
      • 获取对象类型
      • 实例属性和类属性
      • 使用slots
      • 使用@property
      • 多重继承
      • 定制类
        • str
        • repr
        • _iter
        • getitem
      • 枚举类
      • 元类
    • IO编程
      • 文件读写
      • StringIO和BytesIO
        • StringIO
        • BytesIO
      • 操作文件和目录
      • 序列化
        • JSON
    • 进程和线程
      • 多进程
        • fork()调用
        • multiprocessing
        • Pool
        • 进程间通信
      • 多线程
        • threading
        • Lock
      • ThreadLocal
      • 分布式进程
    • 正则表达式
      • 正则表达式
      • re模块
        • r前缀
        • Match()方法
        • 切分字符串
        • 分组
        • 贪婪匹配
    • 常用内建模块
      • datetime
        • 获取当前时间
        • 获取指定日期和时间
        • datetime转换timestamp
        • timestamp转换为datetime
        • str转换为datetime
        • datetime转换为str
  • 机器学习
    • numpy库

Python

输出函数print

print('字符串')
print(数字)

运算(带有运算符的表达式)

print(数字+数字)

输出到文件中

fp=open('file','a+') #a+代表追加,没有找到文件将自动创建
print('字符串',file=fp)
fp.close()

转义字符

  • 换行:\n
  • 回车:\r
  • 制表符:\t
  • 退格:\b
  • 反斜杠:\\
  • 单引号:'
  • 双引号:"

输出原字符,不让字符转中的转义字符起作用,最后一个字符不能是反斜线,如果需要可以使用“\\”表示

print(r'hello\nworld')

保留字、标识符

查看python的保留字

import keyword
print(keyword.kwlist)

输出结果

['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']

规则

变量、函数、类、模块和其他对象起的名字就叫标识符

规则:

  • 字母、数字、下划线
  • 不能以数字开头
  • 不能是保留字
  • 严格区分大小写

变量

变量由三部分组成:

  • 标识:表示对象所存储的内存地址,使用内置函数id(obj)来获取
  • 类型:表示的是对象的数据类型,使用内置函数type(obj)来获取
  • 值:表示对象所存储的具体数据,使用print(obj)可以将值进行打印输出
name='陈佳浩'
print('标识:',id(name))
print('类型',type(name))
print('值',name)

变量内引用变量

name='陈'
age=23

msg=f'''
name:{name}
age:{age}
'''
print(msg)

name='陈'
age=23

msg=f"name:{name}"
print(msg)
  • 判断一个变量是否是某个类型可以用 isinstance()判断:

    a=12
    b="chen"
    c=True
    print(isinstance(a,int))
    print(isinstance(b,str))
    print(isinstance(c,bool))
    

数据类型

整数,浮点数,字符串,布尔值

n1=123
n2=3.1415926
n3='陈佳浩'
F1=True
F2=False
print (n1,type(n1))
print (n2,type(n2))
print (n3,type(n3))
print (F1,type(F1))
print (F2,type(F2))
print ("十进制",110)
print ("二进制",0b01101110) #0b开头
print ("八进制",0o156)		#0o开头
print ('十六进制',0x6E)		#0x开头

浮点数进行运算时会有误差,通过导入模块decimal可以解决

from decimal import Decimal
print (Decimal('1.1')+Decimal('2.2'))
print (1.1+2.2)

数据类型转换

不同的数据类型不能组合到一起

  • str(obj)其他类型转换为str类型

  • int(obj)其他类型转换为int类型

    (浮点数转换int类型会舍弃小数部分,str类型转换为int类型时,必须是数字字符串,否则报错)

  • float(obj)其他类型转换为float类型

    字符串无法转换为float

n1=123
n2=False
n3=22.99
n4='hello'
print(n1,type(n1),int(n1),type(int(n1)),bool(n1),type(bool(n1)))
print(n2,type(n2),int(n2),type(int(n2)),str(n2),type(str(n2)))
print(n3,type(n3),int(n3),type(int(n3)),str(n3),type(str(n3)))

注释

  • 单行注释:#号开头,换行结束
  • 多行注释:开头和结尾使用三引号
#coding:gbk
"""print(n4,type(n4),int(n4),type
(int(n4)))"""

'''
hahaha
hehehe
牛逼'''

输入函数input

test=(input('测试一下:'))
print(test)

不将开头和结尾的空格计入输入

name=input('你的名字:').strip()
print(name)

计算

input函数生成的变量默认为str类型

n1=(input('值1:'))
n2=(input('值2:'))
print(int(n1)+int(n2))

n1=(input('值1:'))
n2=(input('值2:'))
n1=int(n1)
n2=int(n2)
print(n1+n2)

n1=int(input('值1:'))
n2=int(input('值2:'))
print(n1+n2)

运算符

标准运算符

算数运算符

print(1+2)	#加法运算
print(3-4)	#减法运算
print(5*6)	#乘法运算
print(7/8)	#除法运算
print(9//2)	#整除运算,一正一负,向下取整
print(10%4)	#取余运算,一正一负,要使用公式:余数=被除数-除数*商
print(10**2)#平方运算

赋值运算符

运算顺序从右到左

n1=1+3	#普通赋值
n2=n3=n4=12	#链式赋值(id相同)
n6,n7,n8=1,2,3	#解包赋值

#参数赋值
n5=10
n5+=12
print(n5)
n5-=10
print(n5)
n5*=2
print(n5)
n5/=3
print(n5)
n5//=3
print(n5)
n5**=3
print(n5)
n5%=3
print(n5)

比较运算符

a,b="10","10"
print(a>b)
print(a<b)
print(a<=b)
print(a>=b)
print(a==b)
print(a!=b)
print(a is b) #比较ID
print(a is not b) #同上

布尔值运算

与或非

print('--------and---------')
a,b=1,3
print(a==1 and b==3) #结果为true
print(a==1 and b==4) #结果为false
print(a==2 and b==4) #结果为false
print('---------or---------')
a,b=1,3
print(a==1 or b==3) #结果为true
print(a==1 or b==4) #结果为true
print(a==2 or b==4) #结果为false
print('--------not---------')
a,b=True,False
print(not a) #结果为false
print(not b) #结果为true
print('------in和not in----')
a='chen'
print('c' in a) #结果为true
print('b' in a) #结果为false
print('c' not in a) #结果为false
print('b' not in a) #结果为true

位运算

将数据转换为二进制按位进行与或非运算和移位

print(12&4) #按位与&,同为1时结果为1
print(12|2) #按位或|,只要有一个为1结果为1
print(12<<1) #左移位,左移1位(相当于乘以2)
print(12<<2) #左移位,左移2位(相当于乘以4)
print(12>>1) #右移位,右移1位(相当于除以2)
print(12>>2) #右移位,右移2位(相当于除以4)

运算符优先级

从高到低排列

算术运算 位运算 比较运算 布尔值运算 赋值运算

** *,/,//,% +,- <<,>> & | >,<,>=,<=,==,!= and or =

流程控制

if判断

score=float(input('请输入您的成绩:'))
if score >= 90 and score < 100 :
    print('经检测,您的成绩为优秀,希望继续保持')
elif score >= 70 and score < 90:
    print('经检测,您的成绩为良好,努力还可更进一步')
elif score >= 60 and score < 70:
    print('您的成绩刚及格,这个成绩很危险!')
elif 60 > score >= 0:
    print('您的成绩不及格,希望你能认真对待学习!')
else:
    print('请输入正确的成绩[0~100]之间')

第二种写法(if else)

n1=int(input('第一个值:'))
n2=int(input('第二个值:'))
print('------比较两个数-----')
if n1 >= n2:
    print(n1,'大于等于',n2)
else:
    print(n1,'小于',n2)
print(str(n1)+'大于等于'+str(n2) if n1 >= n2 else str(n1)+'小于'+str(n2))

嵌套if

member=input('您是会员吗[是/不是]?:')
money=float(input('本次消费金额:'))
if member == '是':
    if money >= 200:
        print('您是本店会员,本次消费打八折,需支付:',money * 0.8,'元')
    elif money >= 100:
        print('您是本店会员,本次消费打九折,需支付:',money * 0.9,'元')
    elif money >= 50:
        print('您是本店会员,本次消费打九五折,需支付:',money * 0.95,'元')
    else:
        print('您是本店会员,本次消费不打折,需支付:',money,'元,您的消费太少啦!')
elif member == '不是':
    if money >= 200:
        print('您不是本店会员,本次消费打九折,需支付:',money * 0.9,'元')
    elif money >= 100:
        print('您不是本店会员,本次消费打九五折,需支付:',money * 0.95,'元')
    else:
        print('您不是本店会员,本次消费不打折,需支付:',money,'元,您的消费太少啦!')
else:
    print('您是不是本店会员啊,别让我算错帐啊!')

pass语句

什么都不做,只是一个占位符,用到需要写语句的地方

test=input('测试一下[y/n]:')
if test == 'y':
    pass
elif test == 'n':
    pass
else:
    print('输入错误!')

range函数

  • 用于生成一个整数序列
  • 创建range对象的三种方式
    • range(stop) 创建一个[0,stop]之间的整数序列,步长为1
    • range(start,stop) 创建一个[start,stop]之间的整数序列,步长为1
    • range(start,stop,step)创建一个[start,stop]之间的整数序列,步长为step
  • 返回值是一个迭代器对象(不是具体的数据,使用list函数可以查看)
  • range类型的优点:不管range对象表示的整数序列有多长,所有range对象占用的内存空间都是相同的,因为仅仅需要存储start,stop和step,只有当用到range对象时,才会去计算序列中的相关元素
  • in与not in判断整数序列中是否存在(不存在)指定的整数
n1=range(10)
print(n1)
print(list(n1))

n1=range(0,10)
print(list(n1))
print(5 in n1)
print(1 not in n1)

n1=range(0,10,2)
print(list(n1))
print(5 in n1)
print(1 not in n1)

while循环

n1=1
n2=0
while n1 <= 100:
    if not n1%2:
        n2+=n1
    n1+=1
print(n2)

for-in循环

当在循环体中不需要用到自定义变量,可将自定义变量写为 _

for i in range(5):
    print(i)
for _ in range(5):
    print('人生苦短,何必搞IT')

输出100-999之间的水仙花数(例如:153=1*1*1+5*5*5+3*3*3)

for i in range(100,1000):
    n1=0
    for j in str(i):
        n1+=int(j)**3
        if n1 == i:
            print(i)

break语句

用于结束循环结构,通常和分支结构if一起使用

pwd='chen'
for i in range(3):
    n1=input('请输入密码:')
    if n1 == pwd:
        print('密码正确!')
        break
    else:
        print('密码错误,请重新输入')

与while一起使用

pwd='chen'
i=1
while i <=3:
    i+=1
    n1=input('请输入密码:')
    if n1 == pwd:
        print('密码正确!')
        break
    else:
        print('密码错误,请重新输入')

continue语句

用于结束当前循环,进入下一次循环

for i in range(1,51):
    if i%5!=0:
        continue
    print(i)

else语句

可与if,for,while搭配使用

n1=0
while n1 < 3:
    pwd=input('请输入密码:')
    if  pwd=='chen':
        print('密码正确!')
        break
    else:
        print('密码错误,请重新输入!')
        n1+=1
else:
    print('三次输入错误!')

嵌套循环

九九乘法表

for i in range(1,10):
    for j in range(1,i+1):
        print(j,'x',i,'=',j*i,end='\t')
        if i == j:
            print(end='\n')

列表

变量可以储存一个元素,而列表可以储存多个元素,方便对这些元素进行整体操作

相当于其它语言的数组

特点:

  • 列表元素按顺序有序排序
  • 索引映射唯一个数据
  • 列表可以存储重复数据
  • 任意数据类型混存
  • 根据需要动态分配和回收内存

索引:-1,-2,-3,-4

值 :a,b,c,d

索引:0,1,2,3

创建列表的两种方式

test1=['hello','word',123]
test2=list(['hello','word',321])

取值

test=['hello','word',123]
print(test[0],test[1],test[2])
print(test[-1],test[-2],test[-3])

切片

格式:列表名[start:stop:step]

test=['hello','word',123]
print(test[3:0:-1])
print(test[1:2])

取索引

如果存在相同的元素,只返回相同元素中第一个元素的索引

test=['hello','word',123]
print(test.index(123))

指定一个起始和结束区间

test=['hello','word',123]
print(test.index('word',1,2))

列表元素查询

判断元素是否存在于列表中

使用in、not in

test=['hello','word',123]
print('hello' in test)
print('helloo' not in test)

列表元素遍历

test=['hello','word',123]
for i in test:
    print(i)

列表元素的增删改

列表元素的增加操作

  • append():在列表的末尾添加一个元素
  • expend():在列表的末尾添加至少一个元素(添加对象为列表)
  • insert():在列表的任意位置添加一个元素
  • 切片:在列表的任意位置添加至少一个元素(会覆盖切片位置的内容)
test=['hello','word',123]
test.append('qwer')
print(test)
test.extend([123,'qqqqq'])
print(test)
test.insert(0,'zxc')
print(test)
test[0:8]='chen','jia','hao'
print(test)

列表元素的删除操作

  • remove():一次删除一个元素;重复元素只删除第一个

  • pop():删除一个指定索引位置上的元素;不指定索引,删除列表最后一个元素

  • 切片:一次至少删除一个元素

    • 生成一个新的列表对象
    • 不产生新的列表对象,而是删除原列表中的内容
  • clear():清空列表

  • del:删除列表

test=['chen','chen','jia','hao',123]

test.remove('chen')
print(test)

test.pop(3)
print(test)

test2=test[1:3]
print(test2)

test[0:1]=[]
print(test)

test.clear()
print(test)

del(test)
print(test)

列表元素的修改操作

  • 为指定的索引赋予一个新值
  • 为指定的切片赋予一个新值
    • 使用切片语法赋值时,python不支持单个值,比如:list[4:4] = 33这种写法是错误的,但是如果使用字符串赋值,python会自动把字符串转换成序列,其中每个字符都是一个元素
test=['chen','chen','jia','hao']
test[0]='我的名字是:'
print(test)
test[1:4]='陈佳浩',123
print(test)

列表元素的排序操作

  • 调用stor()方法,列表中的所有元素默认按照从小到大的顺序进行排序,可以指定reverse=True,进行降序排序
  • 调用内置函数sorted(),可以指定reverse=True,进行降序排列,原列表不发生改变
test=[2,4,1,3,5,7,9,6,0,8]
print(test)
test.sort()
print(test)
test.sort(reverse=True)
print(test)
print(sorted(test))
print(test)

列表生成式

生成列表的公式

语法格式:[ i*i for i in range(10) ] 列表元素表达式 for 自定义变量 可迭代变量

test=[i*i for i in range(1,10)]
print(test)

字典

python内置的数据结构之一,与列表一样是一个可变序列

以键值对的方式存储数据,字典是一个无序的序列

字典的创建

  • 最常用方式:使用花括号
test={ '陈': 123,'王': 234 }
  • 使用内置函数dict()
dict( name='陈' ,age=20 )

使用花括号

test={'陈': 123}
print(test,type(test))
print(test['陈'])

使用dict

test=dict(陈='qwe')
print(test,type(test))
print(test['陈'])

创建空字典

test=dict()
test2={}
print(test,type(test),test2,type(test2))

元素获取

字典中元素的获取

  • 方法一:
test['陈']
  • 方法二
test.get('陈')

区别:

使用[]方法,如果字典中不存在指定的key,抛出keyError异常

使用get()方法,如果字典中不存在指定的key,并不会抛出keyError而是返回None,可以通过参数设置默认的value,以便指定的key不存在时返回

test=dict(陈=123,王=000,刘=333)
print(test['陈'],test['王'],test.get('陈'),test.get('刘',99))

key的判断

判断key是否存在字典中

test=dict(陈=123,王=000,刘=333)
print('陈' in test)
print('陈' not in test)

字典元素的增删

  • 删除del
test=dict(陈=123)
print(test['陈'],test.get('王'))
del test['陈']
print(test.get('陈'),test.get('王'))
  • 清空
test=dict(陈=123,王=333)
test.clear()
print(test)
  • 新增
test=dict(陈=123)
print(test['陈'],test.get('王'))
test['王']=444
print(test.get('陈'),test.get('王'))
  • 修改
test=dict(陈=123)
print(test.get('陈'))
test['陈']=333
print(test.get('陈'))

获取字典视图

  • keys():获取字典中所有的key
  • values():获取字典中所有的value
  • items():获取字典中所有key,value对
test=dict(陈=123,王=333)
print(test.keys())
print(test.values())
print(test.items())
print(list(test.items()))	#转换之后的列表元素是由元组组成

字典元素的遍历

字典元素的遍历

test=dict(陈=123,王=333)
for test2 in test:
    print(test2,test[test2])

字典生成式

  • 内置函数zip()

    用于将可迭代的对象作为参数,将对象中对应的元素打包成一个元组,然后返回由这些元组组成的列表

    items=['陈','佳','浩']
    prices=[123,456,789]
    #转换成下面的字典
    #{'陈':123,'佳':456,'浩':789}
    print(list(zip(items,prices)))
    
  • 字典生成式

    {item:price for item,price in zip(items,prices)}
    

元组

元组:python内置的数据结构之一,是一个不可变序列

  • 不可变序列与可变序列
    • 不可变序列:字符串,元组
      • 不可变序列:没有增、删、改操作
    • 可变序列:列表,字典
      • 可变序列:可以对序列进行增、删、改操作,对象地址不发生更改

元组创建方式

  • 元组的创建方式

    • 直接小括号

      test=('陈','佳','浩')
      #小括号可以省略
      print(type(test))
      
    • 使用内置函数tuple()

      test=tuple(('陈','佳','浩'))
      print(type(test))
      
    • 只包含一个元组的元素需要使用逗号和小括号

      test=('陈',)
      print(type(test))
      
  • 注意事项

    • 如果元组中的对象本身是不可变对象,则不能再引用其他对象

    • 如果元组中的对象本身是可变对象,则可变对象的引用不允许改变,但数据可以改变

      test=(10,[11,12],13)
      print(test[0])
      print(test[1])
      print(test[2])
      test[1].append('陈')
      print(test[1])
      print(test)
      

元组的遍历

  • 元组是可迭代对象,所以可以使用for...in...进行遍历

    test=tuple((10,11,12))
    for i in test:
        print(i)
    

集合

  • 集合
    • Python语言提供的内置数据结构
    • 与列表、字典一样都属于可变类型的序列
    • 集合是没有value的字典

集合的创建方式

  • 集合的创建方式

    • 直接{}

      test={12,13,14}
      print(type(test))
      
    • 使用内置函数set()

      #将一个整数序列转换成集合
      test=set(range(10))
      print(test)
      print(type(test))
      #将列表当中的元素转换成集合
      test=set([1,2,3,4,5])
      print(test)
      print(type(test))
      #将元组类型的元素转换成集合
      test=set((1,2,3,4,5))
      print(test)
      print(type(test))
      #字符串序列
      test=set('陈佳浩')
      print(test)
      print(type(test))
      #将集合转换成集合
      test=set({1,2,3,4,5})
      print(test)
      print(type(test))
      #定义一个空集合
      test=set()
      print(test)
      print(type(test))
      

集合的相关操作

  • 集合元素的判断操作

    • in或not in

      test=set({1,2,3,4,5})
      print(1 in test)
      print(6 in test)
      print(2 not in test)
      print(6 not in test)
      
  • 集合元素的新增操作

    • 调用add()方法,一次添加一个元素

      test=set({1,2,3,4,5})
      test.add(6)
      print(test)
      
    • 调用update()方法,至少添加一个元素

      test=set({1,2,3,4,5})
      test.update([6,7])
      print(test)
      
  • 集合元素的删除操作

    • 调用remove()方法,一次删除一个指定元素,如果指定的元素不存在抛出KeyError

      test=set({1,2,3,4,5})
      test.remove(3)
      print(test)
      
    • 调用discard()方法,一次删除一个指定元素,如果指定元素不存在不抛出异常

      test=set({1,2,3,4,5})
      test.discard(6)
      test.discard(3)
      print(test)
      
    • 调用pop()方法,一次只删除一个任意元素,不能指定参数

      test=set({12,33,22,34,5,6,32,1,2,3,4,5})
      test.pop()
      print(test)
      
    • 调用clear()方法,清空集合

      test=set({12,33,22,34,5,6,32,1,2,3,4,5})
      test.clear()
      print(test)
      

集合间的关系

  • 两个集合是否相等

    • 可以使用运算符==或!=进行判断

      test=set({12,34,56})
      test2=set({34,12,56})
      print(test == test2)
      print(test !=test2)
      
  • 一个集合是否是另一个集合的子集

    • 可以调用方法issubset进行判断

      test=set({12,34,56})
      test2=set({34,12})
      print(test2.issubset(test))
      print(test.issubset(test2))
      
  • 一个集合是否是另一个集合的超集

    • 可以调用方法issuperset进行判断

      test=set({12,34,56})
      test2=set({34,12})
      print(test.issuperset(test2))
      print(test2.issuperset(test))
      
  • 两个集合是否没有交集

    • 可以调用方法isdisjoint进行判断

      test=set({12,34,56})
      test2=set({78,90,11})
      test3=set({78,34,90})
      print(test.isdisjoint(test2))
      print(test.isdisjoint(test3))
      

集合的数学操作

  • 查找两个集合之间的交集

    • 调用方法intersection

      test=set({12,34,56,78,90})
      test2=set({23,34,45,56})
      print(test.intersection(test2))
      
    • 使用&符

      test=set({12,34,56,78,90})
      test2=set({23,34,45,56})
      print(test & test2)
      
  • 合并两个集合(并集)

    • 调用方法union

      test=set({12,34,56})
      test2=set({78,90})
      print(test.union(test2))
      
    • 使用|符

      test=set({12,34,56})
      test2=set({78,90})
      print(test | test2)
      
  • 差集操作

    • 调用方法difference

      test=set({12,34,56})
      test2=set({56,78,90})
      print(test.difference(test2))
      print(test2.difference(test))
      
    • 使用-符

      test=set({12,34,56})
      test2=set({56,78,90})
      print(test - test2)
      print(test2 - test)
      
  • 对称差集

    • 调用方法symmetric_difference

      test=set({12,34,56})
      test2=set({56,78,90})
      print(test.symmetric_difference(test2))
      
    • 使用^符

      test=set({12,34,56})
      test2=set({56,78,90})
      print(test2 ^ test)
      

集合生成式

  • 用于生成集合的公式

    {i*i for i in range(1,10)}
    
  • 将{}修改为[]就是列表生成式

  • 没有元组生成式

字符串

  • 字符串

    • 在Python中字符串是基本的数据类型,是一个不可变的字符序列
  • 字符串驻留机制

    • 仅保存一份相同且不可变字符串的方法,不同的值被存放在字符串的驻留池中,Python的驻留机制对相同的字符串只保留一份拷贝,后续创建相同的字符串时,不会开辟新空间,而是把该字符串的地址赋给新创建的变量

      test='陈佳浩'
      test2="陈佳浩"
      test3='''陈佳浩'''
      print(test,id(test))
      print(test2,id(test2))
      print(test3,id(test3))
      
  • 驻留机制的几种情况(交互模式)

    • 字符串的长度为0或1时
    • 符合标识符的字符串
    • 字符串只在编译时进行驻留,而非运行时
    • [-5,256]之间的整数数字
  • sys中的intern方法强制2个字符串指向同一个对象

  • PyCharm和vscode对字符串进行了优化处理

  • 字符串驻留机制的优缺点

    • 当需要值相同的字符串时,可以直接从字符串池里拿来使用,避免繁琐的创建和销毁,提升效率和节约内存,因此拼接字符串和修改字符串是会比较影响性能的
    • 在需要进行字符串拼接时建议使用str类型的join方法,而非+,因为join()方法是先计算出所有字符串中的长度,然后再拷贝,值new一次对象,效率要比+高

字符串查询操作的方法

  • 字符串查询操作的方法

    • 方法名称:index():查找子串substr第一次出现的位置,如果查找的子串不存在时,则抛出ValueError

      test="hello hello"
      print(test.index("lo"))
      
    • 方法名称:rindex():查找子串substr最后一次出现的位置,如果查找的子串不存在时,则抛出ValueError

      test="hello hello"
      print(test.rindex("lo"))
      
    • 方法名称:find():查找子串substr第一次出现的位置,如果查找的字串不存在时,则返回-1

      test="hello hello"
      print(test.find("lo"))
      
    • 方法名称:rfind():查找子串substr最后一次出现的位置,如果查找的子串不存在时,则返回-1

      test="hello hello"
      print(test.rfind("lo"))
      

字符串判断

a.startswith( 
a.endswith( 
a.isalnum( 是不是字⺟or数字
a.isalpha( 是不是字⺟
a.isascii( 暂不⽤,没学
a.isdecimal( 不要⽤, 垃圾
a.isdigit( 是不是数字
a.isidentifier( 是不是合法的可以做变量的名字
a.islower( 
a.isnumeric( 是不是数字,可判断中文例如“二十”
a.isprintable( 是否可打印
a.isspace( 是不是空格
a.istitle( 
a.isupper(

字符串查找&计数&修改&替换

a.find( 
a.rfind( 
a.index( 
a.rindex( 
a.count( 
a.rsplit( 
a.split( 
a.splitlines( 
a.removeprefix(
a.removesuffix(
a.replace(

###字符串的大小写转换操作的方法

  • 字符串的大小写转换操作的方法

    • 方法名称:upper():把字符串中所有字符都转成大写字母

      test="hello word"
      print(test.upper())
      
    • 方法名称:lower():把字符串中所有字符都转成小写字母

      test="HELLO WORD"
      print(test.lower())
      
    • 方法名称:swapcase():把字符串中所有大写字母转成小写字母,把所有小写字母转成大写字母

      test="hello WORD"
      print(test.swapcase())
      
    • 方法名称:capitalize():把第一个字符转换为大写,把其余字符转换为小写

      test="hello WORD"
      print(test.capitalize())
      
    • 方法名称:title():把每个单词的第一个字符转换为大写,把每个单词的剩余字符转换为小写

      test="hello WORD"
      print(test.title())
      

字符串内容对齐操作的方法

  • 字符串内容对齐操作的方法

    • 方法名称:center():居中对齐,第一个参数指定宽度,第二个参数指定填充符,第二个参数是可选的,默认是空格,如果设置宽度小于实际宽度则返回原字符串

      test="hello word"
      print(test.center(12,"*"))
      
    • 方法名称:ljust():左对齐,第一个参数指定宽度,第二个参数指定填充符,第二个参数是可选的,默认是空格,如果设置宽度小于实际宽度则返回原字符串

      test="hello word"
      print(test.ljust(12,"*"))
      
    • 方法名称:rjust():右对齐,第一个参数指定宽度,第二个参数指定填充符,第二个参数是可选的,默认是空格,如果设置宽度小于实际宽度则返回原字符串

      test="hello word"
      print(test.rjust(12,"*"))
      
    • 方法名称:zfill():右对齐,左边用0填充,该方法只接收一个参数,用于指定字符串的宽度,如果指定的宽度小于等于字符串的长度,则返回字符串本身

      test="hello word"
      print(test.zfill(12))
      

字符串劈分操作的方法

  • 字符串劈分操作的方法

    • 方法名称:split():从字符串的左边开始劈分,默认的劈分字符是空格字符串,返回的值都是一个列表

      test="hello word python"
      print(test.split())
      
      • 以通过参数sep指定劈分字符串时的劈分符

        test="hello,word,python"
        print(test.split())
        print(test.split(sep=","))
        
      • 通过参数maxsplit指定劈分字符串时的最大劈分次数,在经过最大次劈分之后,剩余的子串会单独作为一部份

        test="hello word python"
        print(test.split(maxsplit=1))
        
    • 方法名称:rsplit():从字符串右边开始劈分,默认的劈分字符是空格字符串,返回的值都是一个列表

      test="hello,word,python"
      print(test.rsplit())
      
      • 以通过参数sep指定劈分字符串时的劈分符

        test="hello,word,python"
        print(test.rsplit())
        print(test.rsplit(sep=","))
        
      • 通过参数maxsplit指定劈分字符串时的最大劈分次数,在经过最大次劈分之后,剩余的子串会单独作为一部份

        test="hello,word,python"
        print(test.rsplit())
        print(test.rsplit(sep=",",maxsplit=1))
        

判断字符串操作的方法

  • 判断字符串操作的方法

    • 方法名称:isidentifier():判断指定的字符串是不是合法的标识符(字母、数字、下划线)

      test="陈_chen_12"
      test2="陈,chen"
      print(test.isidentifier())
      print(test2.isidentifier())
      
    • 方法名称:isspace():判断指定的字符串是否全部由空白字符组成(回车、换行、水平制表符)

      test="\r\t\n"
      test2="rtn"
      print(test.isspace())
      print(test2.isspace())
      
    • 方法名称:isalpha():判断指定的字符串是否全部由字母组成

      test="abc"
      test2="123"
      print(test.isalpha())
      print(test2.isalpha())
      
    • 方法名称:isdecimal():判断指定字符串是否全部由十进制的数字组成

      test="123"
      test2="一二三"
      print(test.isdecimal())
      print(test2.isdecimal())
      
    • 方法名称:isnumeric():判断指定字符串是否全部由数字组成

      test="123"
      test2="一二三"
      print(test.isnumeric())
      print(test2.isnumeric())
      
    • 方法名称:isalnum():判断指定字符串是否全部由字母和数字组成

      test="abc123"
      test2="abc123!"
      print(test.isalnum())
      print(test2.isalnum())
      

字符串操作的其他方法

字符串的替换

  • 字符串的替换

    • 方法名称:replace():第一个参数指定被替换的子串,第二个参数指定替换子串的字符串,该方法返回替换后得到的字符串,替换前的字符串不发生变化,调用该方法时可以通过第三个参数指定最大替换次数

      test="hello word python hello word python"
      print(test.replace("hello word","hi"))
      print(test.replace("hello word","hi",1))
      

字符串的合并

  • 字符串的合并

    • 方法名称:join():将列表或元组中的字符串合并成一个字符串

      test=["hello","word","python"]
      print("|".join(test))
      

字符串的比较操作

  • 字符串的比较操作

    • 运算符:>,<=,<,<=,==,!=

    • 比较规则:首先比较两个字符串中的第一个字符,如果相等,则继续比较下一个字符,依次比较下去,直到两个字符串中的字符不相等时,其比较结果就是两个字符串的比较结果,两个字符串中所有后续字符将不再被比较

    • 比较原理:两个以上字符进行比较时,比较的是其ordinal value(原始值),调用内置函数ord可以得到指定字符ordinal value。与内置函数ord对应的是内置函数chr,调用内置函数chr时指定ordinal value可以得到其对应的字符

      test="陈"
      test2="佳"
      print(test > test2)
      print(ord(test),ord(test2))
      print(chr(38472),chr(20339))
      

字符串的切片操作

  • 字符串的切片操作

    • 字符串是不可变类型

      • 不具备增、删、改等操作

      • 切片操作将产生新的对象

        test="hello word"
        #print(test[start:end:step])
        print(test[0:5])
        print(test[:2])
        print(test[6:])
        print(test[:2]+"like"+test[6:])
        print(test[::-1]) #从字符串最后一个元素开始,到第一个元素结束
        

格式化字符串

  • 格式化字符串:按一定格式输出的字符串

    • 格式化字符串的两种方式

      • %作占位符,字符串%s,整数%i或%d,浮点数%f

        name="陈佳浩"
        age=23
        print("我叫%s,今年%i岁了" % (name,age))
        
      • {}作占位符,需要调用format方法

        name="陈佳浩"
        age=23
        print("我叫{0},今年{1}岁了".format(name,age))
        
      • f-string格式化

        name="陈佳浩"
        age=23
        print(f"我叫{name},今年{age}岁了")
        
    • 其他操作

      • 锁定宽度

        print('%10d' % 99)
        
      • 锁定精度(小数点后几位)

        print('%.3f' % 3.1415926)
        
      • 同时锁定宽度和精度

        print('%10.3f' % 3.1415926)
        
      • 另一种写法

        print('{0:10.3f}'.format(3.1415926)) #0表示占位符的顺序
        print('{0:10.3}'.format(3.1415926)) #.3表示一共三位数
        

格式化输出方法

a.capitalize( ⾸字符改成⼤写
a.casefold( 为了⽅便字符串之前对⽐,都改成⼩写
a.center( 字符串两边填充
a.expandtabs( 
a.ljust( 字符串左边填充
a.rjust( 字符串右填充
a.lower( 全变⼩写
a.swapcase( ⼤⼩写互换
a.title( 改成标题,即每个单词⾸字⺟⼤写
a.upper( 改⼤写
a.zfill( 字符串空的地⽅填0
a.strip( 两边去死⽪
a.lstrip( 左边去死⽪
a.rstrip( 右边去
a.format( 引⽤外部变量
  • 字符串的编码转换

    • 编码与解码的方式

      • 编码:将字符串转换为二进制数据(bytes)

        test="陈佳浩"
        print(test.encode(encoding='GBK')) #在GBK这种编码中,一个中文字符占两个字节
        print(test.encode(encoding='UTF-8')) #在UTF-8这种编码中,一个中文字符占三个字节
        
      • 解码:将bytes类型的数据转换成字符串类型

        test="陈佳浩"
        test2=test.encode(encoding='UTF-8')
        print(test2.decode(encoding="UTF-8"))
        

函数

函数的创建和调用

  • 函数的创建和调用

    def test (a,b,c):	#test为函数名,a,b,c为占位符
        test2=a+b+c
        return test2	#return结束函数,返回test2的结果
    print(test("陈","佳","浩"))
    

函数的参数传递

  • 函数调用的参数传递

    • 位置实参

      • 根据形参对应的位置进行实参传递

        def test (a,b,c):	#a,b称为形式参数,简称形参,形参的位置是在函数的定义处
            test2=a+b+c
            return test2
        print(test("陈","佳","浩"))	#"陈","佳","浩"成为实际参数,简称实参,实参的位置是在函数的调用处
        
    • 关键字实参

      • 根据形参名称进行实参传递

        def test (a,b,c):
            test2=a+b+c
            return test2
        print(test(c="浩",a="陈",b="佳"))	#左边的变量的名称a,b,c称为关键字参数
        

函数的返回值

  • 函数的返回值

    • 如果函数没有返回值(函数执行完毕后,不需要给调用处提供数据)return可以省略不写

      def test():
          print("hello word")
      
      test()
      
    • 函数的返回值如果是一个,直接返回原类型

      def test(a):
          b=a+2
          return b
      print(test(2),type(test(2)))
      
    • 函数返回多个值时,结果为元组

      def test(num):
          odd=[]
          even=[]
          for i in num:
              if i%2:
                  odd.append(i)
              else:
                  even.append(i)
          return odd,even
      print(test([1,2,3,4,5,6,7,8,9]))
      

函数的参数定义

  • 函数的参数定义

    • 函数定义默认值参数

      • 函数定义时,给形参设置默认值,只有与默认值不符的时候才需要传递实参

        def test(a,b=20):
            return a,b
        
        print(test(10))
        print(test(10,11))
        
    • 个数可变的位置参数

      • 定义函数时,可能无法事先确定传递的位置实参的个数时,使用可变的位置参数

      • 使用*定义个数可变的位置形参

      • 结果为一个元组

        def test(*a):
            print(a)
        
        test(1)
        test(1,2)
        test(1,2,3)
        
    • 个数可变的关键字形参

      • 定义函数时,无法事先确定传递的关键字实参的个数时,使用可变的关键字形参

      • 使用**定义个数可变的关键字形参

      • 结果为一个字典

        def test(**a):
            print(a)
        
        test(w=1)
        test(q=1,w=2)
        test(q=1,w=2,e=3)
        
    • 在一个函数定义过程中,既有个数可变的关键字形参,也有个数可变的位置形参,要求:个数可变的位置形参放在个数可变的关键字形参之前

      def test(**a,*b):
          pass
      
      def test(*b,**a):
          pass
      
    • 总结

      def test(a,b,c):    #a,b,c在函数定义除,所以是形式参数
          print("a=",a)
          print("b=",b)
          print("c=",c)
      
      test(1,2,3) #函数调用时的参数传递,称为位置传参
      test(*[4,5,6])  #在函数调用时,将列表中的每个元素都转换为位置实参传入
      test(b=8,a=7,c=9)   #函数的调用,所以是关键字实参
      test(**{'a':10,'b':11,'c':12})  #在函数调用时,将字典中的键值对都转换为关键字实参传入
      
      def test2(*a):  #个数可变的位置形参
          print(a)
      
      def test3(**a): #个数可变的关键字形参
          print(a)
      
      test2(1,2,3)
      test3(q=2,c=3)
      
      def test4(a,b,c,d):
          print('a=',a)
          print('b=',b)
          print('c=',c)
          print('d=',d)
      
      test4(13,14,15,16)  #位置实参传递
      test4(a=17,b=18,c=19,d=20) #关键字实参传递
      test4(21,22,c=23,d=24)  #前两个参数使用位置实参传递,c和d使用关键字实参传递
      
      def test5(a,b,*,c,d):   #从*之后的参数,在函数调用时只能使用关键字参数
          print('a=',a)
          print('b=',b)
          print('c=',c)
          print('d=',d)
      #test5(13,14,15,16)
      test5(a=25,b=26,c=27,d=28)
      test5(29,30,c=31,d=32)
      

变量的作用域

  • 变量的作用域

    • 程序代码能访问该变量的区域

    • 根据变量的有效范围可分为

      • 局部变量
        • 在函数内定义并使用的变量,只在函数内部有效,局部变量使用global生命,这个变量就会成全局变量
      • 全局变量
        • 函数体外定义的变量,可作用于函数内外
      a=100
      def test():
          print(a)
          global b	#在函数内指定全局变量
          b=10
          print(b)
      
      print(a)
      print(b)
      test()
      

递归函数

  • 递归函数
    • 什么是递归函数
      • 如果在一个函数体内调用了该函数本身,这个函数就称为递归函数

        def test(a):
            if a == 1:
                return 1
            else:
                return a*test(a-1)
        
        print(test(6))
        
    • 递归的组成部分
      • 递归调用与递归终止条件
    • 递归的调用过程
      • 每递归调用一次函数,都会在栈内存分配一个栈帧
      • 每执行完一次函数,都会释放相应的空间
    • 递归的优缺点
      • 缺点:占用内存多,效率低下
      • 优点:思路和代码简单

map函数

  • map函数接收两个参数,一个函数,一个可迭代序列,将函数依次作用于序列中的每个值
def test(n):
    p=n*n
    return p
ll=[i for i in range(10)]
aa=map(test, ll)
bb=list(aa)
print(bb)

reduce函数

  • Python3中需要引入模块才能使用这个函数

  • reduce函数接收两个参数,一个函数,一个序列,reduce将函数作用在一个序列上,并将结果继续和序列的下一个元素做累计计算

    from functools import reduce
    def test(n,x):
        p=n*x
        return p
    ll=[i for i in range(1,10)]
    aa=reduce(test, ll)
    print(aa)
    
    from functools import reduce
    
    def test(x,y):
        return x*10+y
    a=[1,2,3,4,5]
    b=reduce(test,a)
    print(b)
    

sum函数

用于序列求和运算

a=[i for i in range(1,101)]
print(sum(a))

Bug

Bug的常见类型

序号 异常类型 描述
1 ZeroDivisionError 除(或取模)零(所有数据类型)
2 IndexError 序列中没有此索引(index)
3 KeyError 映射中没有这个键
4 NameError 未声明/初始化对象(没有属性)
5 SyntaxError Python语法错误
6 ValueError 传入无效的参数

Python的异常处理机制

####被动掉坑问题的解决方案try

  • Python提供了异常处理机制(try...except),可以在异常出现时即时捕获,然后内部”消化“,让程序继续运行

    try:
        a=int(input('请输入被除数:'))
        b=int(input('请输入除数:'))
        print(a/b)
    except ZeroDivisionError:   #except后跟会出现的错误类型
        print('除数不能为0')
    print('结束')
    
  • 多个except结构

    try:
        a=int(input('请输入被除数:'))
        b=int(input('请输入除数:'))
        print(a/b)
    except ZeroDivisionError:   #except后跟会出现的错误类型
        print('除数不能为0!')
    except ValueError:
        print('请输入数字类型!')
    print('程序结束。')
    
  • try...except...else结构

    • 如果try块中没有抛出异常,则执行else块,如果try中抛出异常,则执行except块

      try:
          print(int(input("请输入:")))
      except ValueError as e:
          print("错误!",e)
      else:
          print('else')
      
  • try...except...else...finally结构

    • finally块无论是否发生异常都会被执行,能常用来释放try块中申请的资源

      try:
          print(int(input("请输入:")))
      except ValueError as e:
          print("错误!",e)
      else:
          print('成功!')
      finally:
          print('无论如何都会执行!')
      

traceback模块

  • 使用traceback模块打印异常信息

    import traceback
    try:
        print('嘿嘿')
        print(1/0)
    except:
        traceback.print_exc()
    

raise使用

当程序出现错误时,Python会自动引发异常,也可以通过raise显示地引发异常,一旦执行了raise语句,raise后面的语句将不能执行

name="chen"
#name="11"
if name.isalpha():
    print(name)
else:
    raise ValueError("错误的名字!")

开发环境的调试

  • 断点
    • 程序运行到此处,暂时挂起,停止执行。此时可以详细观察程序的运行情况,方便做出进一步的判断
  • 进入调试视图
    • 进入调试视图的三种方式(PyCharm)
      • 单击工具栏上的按钮
      • 右键单击编辑区:点击debug模块名
      • 快捷键:shift+F9

练习

lst=[{'rating':[9.7,2062397],'id':'1292052','type':['犯罪','剧情'],'title':'肖申克的救赎','actors':['蒂姆·罗宾斯','摩根·弗里曼']},
     {'rating':[9.6,1528760],'id':'1291546','type':['剧情','爱情','同性'],'title':'霸王别姬','actors':['张国荣','张丰毅','巩俐','葛优']},
     {'rating':[9.5,1559181],'id':'1292720','type':['剧情','爱情'],'title':'阿甘正传','actors':['汤姆·汉克斯','罗宾·怀特']}
    ]
name=input('请输入要查询的演员:')
for i in lst:
    if name in (i['actors']):
        print(i['title'])

编程思想

  • 编程界的两大阵营

    • 区别:

      • 面向过程:事物比较简单,可以用线性思维去解决
      • 面向对象 :事物比较复杂,使用简单的线性思维无法解决
    • 共同点:

      • 事物比较复杂,使用简单的线性思维无法解决
    • 二者相辅相成,并不是对立的

      解决复杂问题,通过面向对象方式便于从宏观上把握事物之间复杂的关系,方便我们分析整个系统;具体到微观操作,仍然使用面向过程方式来处理

类与对象

    • 类别,分门别类,物以类聚,人类,鸟类,动物类,植物类......
  • 类是多个类似事物组成的群体的统称,能够帮助我们快速理解和判断事物的性质

类与对象

  • 数据类型

    • 不同的数据类型属于不同的类

    • 使用内置函数查看数据类型

      print(type(123))
      print(type('哈哈哈'))
      print(type(3.14))
      
  • 对象

    • 0、34、100都是int类之下包含的相似的不同个例,这个个例专业术语称为实例或对象

      print(type(100))
      print(type(0))
      print(type(34))
      

类与实例及访问限制

我使用了 一段判断成绩的脚本来作为实例,其中test作为一个类,其下有List、find、get_name、get_score、set_name、set_score作为方法,aa、bb、cc、dd则是实例

这里面还用到了__双下划线,双下划线用在这里例如__name则表示这是一个私有变量,只有内部可以访问,外部不可以访问

py={"chen":12,"wang":22,"li":60,"zhao":70,"sun":80,"qian":90}

class test(object):
  
    def __init__(self,first,secend):
        self.__name=first
        self.__score=secend

    def List(self):
        return ('%s:%s' % (self.__name,self.__score))
  
    def find(self):
        if self.__score < 60:
            return ('%s:%s,不及格' % (self.__name,self.__score))
        elif self.__score <80:
            return ('%s:%s,及格' % (self.__name,self.__score))
        elif self.__score <90:
            return ('%s:%s,良好' % (self.__name,self.__score))
        else:
            return ('%s:%s,优秀' % (self.__name,self.__score))

    def get_name(self):
        return self.__name
  
    def get_score(self):
        return self.__score
  
    def set_name(self,name):
        if name.isalpha():
            self.__name=name
        else:
            raise ValueError("错误的名字!")

    def set_score(self,score):
        if str(score).isdigit() and int(score) >=0 and int(score) <=100:
            self.__score=score
        else:
            raise ValueError("错误的成绩!")
  
#for i in py:
    #aa=test(i,py[i])
    #print(aa.List())
    #bb=test(i,py[i])
    #print(bb.find())
    #cc=test(i,py[i])
    #print(cc.get_name())
    #print(cc.__name)
dd=test("chen",12)

dd.set_name("wang")
print(dd.get_name())
dd.set_score("33")
print(dd.get_score())

继承和多态

  • 继承:子类可以获得父类的全部功能,isinstance函数可以判断一个实例的类,下面的例子可以得出,bb(test2)继承自test,当查看bb的类时,它可以是test2,也可以是test(父类)。

    class test():
    
        def run(self):
            print("程序运行!")
    
    #aa=test()
    #aa.run()
    
    class test2(test):
        pass
    
    #bb=test2()
    #bb.run()
    
    aa=test()
    bb=test2()
    print(isinstance(aa,test))
    print(isinstance(bb,test2))
    print(isinstance(bb,test))
    
  • 多态:前面说子类可以继承父类的所有功能,但是,当子类定义了和父类不同的功能时,总是会调用子类的方法,这就是继承的另一个好处,多态。多态有一个好处,就是任何依赖父类作为参数的函数或者方法都可以不加修改地正常运行,只要接收父类地类型就可以,因为子类都属于父类的类型,都有相同的方法,因此,只要传入的是子类的类型,就会自动调用实际类型的方法。这就是多态。

    class test1():
    
        def run(self):
            return "test1 is running"
    
    class test2(test1):
    
        def run(self):
            return "test2 is running"
    
    class test3(test1):
    
        def run(self):
            return "test3 is running"
    
    #bb=test2()
    #bb.run()
    
    aa=test1()
    bb=test2()
    cc=test3()
    print(aa.run())
    print(bb.run())
    print(cc.run())
    
    def run_twice(test):
        print(test.run())
        print(test.run())
    
    run_twice(test1())
    

获取对象类型

通过 type()函数或引入 types模块可查看对象的类型,也可以使用 isinstance()函数

实例属性和类属性

  • 绑定实例属性使用 self

  • 绑定类属性可以在 class中定义

    class Student(object):
        count=0
    
        def __init__(self, name):
            self.name = name
            Student.count+=1
    
    aa=Student("ss")
    print(Student.count)
    
    bb=Student("cc")
    print(Student.count)
    

使用__slots__

  • 限制实例属性,只允许对实例添加某些属性,只对当前实例起作用,不会对子类起作用

    class test():
        __slots__=("name","age")
    
    a=test()
    a.name="chen"
    a.age=23
    #a.score=12
    

使用@property

  • python内置的装饰器,负责把一个方法变成属性调用

  • 将一个方法变成属性只需要加上 @property就可以了,此时,@property本身又创建了另外的装饰器 @name.setter负责把一个setter方法变成属性赋值,于是我们就有了一个可控的属性操作,@name.getter负责把一个getter方法变成返回属性的值。

    class Student(object):
    
        @property
        def name(self):
            #return self.__name
            pass
    
        @name.setter
        def name(self,ss):
            self.__name=ss
    
        @name.getter
        def name(self):
            return self.__name
    
    ss=Student()
    ss.name="chen"
    print(ss.name)
    

多重继承

  • 子类可以继承多个父类,通过多重继承,一个子类就可以获得多个父类的所有功能,这种设计通常称之为MixIn。

    class aMixIn(object):
        pass
    class qMixIn(object):
        pass
    class w(aMixIn,qMixIn):
        pass
    
    s = w()
    print(isinstance(s,aMixIn))
    print(isinstance(s,qMixIn))
    

定制类

类似 __slots____len__()__len__()方法能让class作用域 len()函数,除此之外,Python的class中还有许多这样有特殊用途的函数,可以帮助我们定制类

__str__

  • 定义好 __str__()方法,可以使用格式化字符串,使得返回一个好看的字符串,而不是一串 <__main__.test object at 0x000002768D569E20>

    class test(object):
    
        def __init__(self,name) -> None:
            self.name=name
    
        def __str__(self) -> str:
            return "name变量的值是:%s" % self.name
    
    aa=test("chen")
    print(aa)
    

__repr__

  • 教程上说 __str__()返回的是用户看到的字符串,__repr__()返回的是程序开发者看到的字符串,也就是说 __repr__()是为调式服务的,但是在我练习时,发现这两个函数的作用是一模一样的

  • 当两段代码一样时,有个偷懒的写法

    class test(object):
    
        def __init__(self,name) -> None:
            self.name=name
    
        def __str__(self) -> str:
            return "name变量的值是:%s" % self.name
    
        __repr__=__str__
    
    print(test("chen"))
    s=test("chen")
    print(s)
    

__iter__

  • 如果一个类想被用于 for...in循环,就必须实现一个 __iter__()方法,该方法返回一个迭代对象,然后Python的循环就会不断地调用该迭代对象的 __next__()方法拿到循环的下一个值,直到遇到 StopIteration错误时退出循环。

    class test(object):
    
        def __init__(self) -> None:
            self.num = 0
    
        def __iter__(self):
            return self
    
        def __next__(self):
            self.num+=1
            if self.num >10:
                raise ValueError("错误!")
            return self.num
    
    for i in test():
        print(i)
    

__getitem__

  • 可以将其当作list使用,如果想要切片操作,还需要再额外增加判断。

    class test(object):
    
        def __getitem__(self,n):
            a=0
            for i in range(n):
                a+=1
            return a
    
    b=test()
    print(b)
    print(b[9])
    

枚举类

from enum import Enum,unique

Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

for name, member in Month.__members__.items():
    print(name, '=>', member, ',', member.value)
print(Month.__members__.items())
print(Month.Feb.value)

#@unique
class week(Enum):
    Mon=1
    Tue=2
    Wed=3
    Thu=4
    Fri=5
    Sat=6
    Sun=7

day1=week.Mon
print(day1.value)

元类

  • type()函数既可以返回一个对象的类型,又可以创建出新的类型

  • 要创建一个class对象 type()函数依次传入三个参数:

    • class的名称
    • 继承的父类集合,支持多重继承
    • class的方法名称与函数绑定,下面将函数 test绑定到 hello
    def test(self,name):
        print(name)
    HH=type('Hello',(),dict(hello=test))
    print(type(HH))
    hh=HH()
    hh.hello("ss")
    

IO编程

文件读写

  • 读文件,需要 openreadclose,Python引入了 with语句来自动帮忙调用 close()

    test=open('./test.txt',"r",encoding='utf-8')
    print(test.read())
    print(test.read(1))
    print(test.readline())
    print(test.readlines())
    test.close()
    
    with open('./test.txt',"r",encoding='utf-8') as f:
        print(f.read())
    
  • 写文件和读文件一样,区别是调用 open()函数时,传入标识符 w

    test=open('./test.txt','w')
    test.write("ssss")
    test.close()
    

StringIO和BytesIO

StringIO

  • 可以在内存中进行读写,而不是在文件中

    from io import StringIO
    
    class test():
    
        a=StringIO()
    
        def Writ(self,name):
            self.name=name
            return test.a.write(self.name)
    
        def Get(self):
            return test.a.getvalue()
    ss=test()
    
    print(ss.Writ("陈"))
    print(ss.Get())
    

BytesIO

  • StringIO操作的只能是str,如果要操作二进制数据,就需要使用 BytesIO

  • 需要加上编码格式

    from io import BytesIO
    
    class test():
    
        a=BytesIO()
    
        def Writ(self,name):
            self.name=name
            return test.a.write(self.name.encode('utf-8'))
    
        def Get(self):
            return test.a.getvalue()
    ss=test()
    
    print(ss.Writ("陈"))
    print(ss.Get())
    

操作文件和目录

  • python的 os模块封装了操作系统的目录和文件操作,这些函数有些在 os模块中,有些在 os.path模块中。

    import os
    
    print(os.name)
    #print(os.uame())
    print(os.environ)
    print(os.environ.get('VSCODE_INJECTION'))
    
    print(os.path.abspath('.'))
    print(os.path.join('C:\\Users\\placj\\Desktop\\代码\\python','linshi.txt'))
    os.mkdir('C:\\Users\\placj\\Desktop\\代码\\python\\linshi.txt')
    os.rmdir('C:\\Users\\placj\\Desktop\\代码\\python\\linshi.txt')
    print(os.path.split("C:\\Users\\placj\\Desktop\\代码\\python\\linshi.txt"))
    print(os.path.splitext("C:\\Users\\placj\\Desktop\\代码\\python\\linshi.txt"))
    os.rename('test.txt','test.sh')
    os.remove('test.sh')
    

序列化

  • 把变量从内存中变成可存储或传输的过程称之为序列化

    import pickle
    
    d="qwer"
    f=open("test.txt","wb")
    pickle.dump(d,f)
    f.close()
    
    f=open("test.txt","rb")
    d=pickle.load(f)
    f.close
    print(d)
    

JSON

  • 如果要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,JSON表示出来的就是一个字符串,可被所有语言读取。

    import json
    b={"name":"chen","age":23}
    f=open("test.txt","w")
    json.dump(b,f)
    f.close()
    
    f=open("test.txt","r")
    b=json.load(f)
    f.close()
    print(b)
    

进程和线程

多进程

fork()调用

  • Unix/Linux操作系统提供了一个 fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是 fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。

  • 调用函数 os.fork()会将程序执行两次,并每次返回一个值,父进程返回子进程的pid,子进程永远返回0

  • 使用方法 os.getpid()可以获得当前进程的pid,使用方法 os.getppid()可以获得父进程的pid

    import os
    
    qq=os.fork()
    
    if qq==0:
            print("I am (%s),is (%s) create me" % (os.getpid(),os.getppid()))
    else:
            print("I am (%s) create (%s)" % (os.getpid(),qq))
    

multiprocessing

  • multiprocessing是一个跨平台的多进程模块

  • multiprocessing模块提供了一个 Process类来代表一个进程对象

  • 创建子进程时,需要传入一个执行函数 target和函数的参数 args创建一个 Process实例,用 start()方法启动子进程,if __name__=='__main__':必须要写,目前还不懂啥意思

  • join()方法可以等子进程结束后再往下执行

    from multiprocessing import Process
    import os
    
    def child(name):
        print("I am child: %s,to print %s,is %s create me" % (os.getpid(),name,os.getppid()))
    
    if __name__=='__main__':
        p=Process(target=child,args=('chen',))
        print("I am father: %s" % os.getpid())
        p.start()
        p.join()
        print("I am %s" % os.getpid())
    

Pool

  • 如果要创建大量的子进程,可以用进程池的方式批量创建子进程

  • Pool对象调用 join()方法会等待所有子进程执行完毕,调用 join()之前必须调用 close(),调用 close()之后就不能继续添加新的 Process

  • 下面例子 p=Pool(3)设置可以同时跑3个子进程,默认大小是CPU的核数

    from multiprocessing import Pool
    import os
    
    def child(name):
        print("I am child: %s,to print %s,is %s create me" % (os.getpid(),name,os.getppid()))
    
    if __name__=='__main__':
        p=Pool(3)
        for i in range(10):
            p.apply_async(child,args=("chen",))
        p.close()
        p.join()
        print("over!")
    
    

进程间通信

  • Process之间肯定是要通信的,操作系统提供了很多机制来实现进程间的通信,Python的 multiprocessing模块包装了底层的机制,提供了 QueeuPipes等多种方式来交换数据。

    from multiprocessing import Process, Queue
    import os
    
    def write(q,aa):
        print('进程%s正在写入。。。' % os.getpid())
        #a=["chen","jia","hao","niu bi"]
        for i in aa:
            print('写入%s' % i)
            q.put(i)
    
    def read(q):
        print('进程%s正在读取。。。' % os.getpid())
        #while True:
        #    value=q.get(True)
        #    print('获取数据:%s' % value)
        print('姓:%s' % q.get(True))
        print('名:%s%s' % (q.get(True),q.get(True)))
    
    if __name__=='__main__':
        aa=input("请输入:")
        #print(aa)
        #bb=list(aa.split())
        q=Queue()
        pw=Process(target=write,args=(q,aa))
        pr=Process(target=read,args=(q,))
        pw.start()
        pr.start()
        pw.join()
        pr.terminate()
    

多线程

threading

  • 多任务可以由多进程完成,也可以由一个进程内的多个线程完成

  • Python的标准库提供了两个模块:_threadthreading_threads是低级模块,threading是高级模块,对 _thread进行了封装,绝大多数情况下,我们只需要用 threading这个高级模块。

  • 启动一个线程就是把一个函数传入并创建 Thread实例,然后调用 start()开始执行。

  • 由于任何进程默认就会启动一个线程,我们把该线程称为主线程,主线程又可以启动新的线程,Python的 threading模块有个 current_thread()函数,他永远返回当前线程的实例,主线程实例的名字叫做 MainThread,子线程的名字在创建时指定,我用 Child thread命名子线程,名字仅仅在打印时显示,完全没有其他任何意义,如果不起名,默认命名为 Thread-1

    import threading
    
    def test():
        n=0
        while n < 5:
            n+=1
            print("线程:%s" % threading.current_thread().name,n)
        print("线程%s执行完毕" % threading.current_thread().name)
    
    if __name__=='__main__':
        print("线程:%s" % threading.current_thread().name)
        t=threading.Thread(target=test,name='Child thread')
        t.start()
        t.join()
        print("线程%s执行完毕" % threading.current_thread().name)
    

Lock

  • 进程和线程最大的不同在于,多进程中,同一个变量,各自由一份拷贝,存在于每个进程中,互不影响,而在多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,存在变量内容被改乱的情况

  • 如果要确保变量正确,就需要给修改操作上一把锁,当某个线程开始执行修改操作时,就会获得一个锁,同时其他线程将不能进行修改,只能等待,直到该锁释放。创建一个锁就是通过 threading.Lock()来实现

    import time, threading
    
    # 假定这是你的银行存款:
    balance = 0
    lock=threading.Lock()
    
    def change_it(n):
        # 先存后取,结果应该为0:
        global balance
        balance = balance + n
        balance = balance - n
    
    def run_thread(n):
        for i in range(2000):
            # 先获取锁
            lock.acquire()
            try:
                # 进行修改
                change_it(n)
            finally:
                # 释放锁
                lock.release()
    
    t1 = threading.Thread(target=run_thread, args=(5,))
    t2 = threading.Thread(target=run_thread, args=(8,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(balance)
    

ThreadLocal

  • ThreadLocal解决了变量在每层函数中的传递问题

  • 下例中,全局变量 test就是一个 TheadLocal对象,每个 Thread对他都可以读写 tt属性,但互不影响,可以把 test看成全局变量,但没个属性如 test.tt都是线程的局部变量,可以任意读写且互不干扰,也不用管理锁的问题,ThreadLocal内部会处理。

    import threading
    
    test=threading.local()
    
    def demo1():
        name=test.tt
        print("测试,线程%s值:%s" % (threading.current_thread().name,name))
    
    def demo2(name):
        test.tt=name
        demo1()
    
    t1=threading.Thread(target=demo2,args="陈",name="1")
    t2=threading.Thread(target=demo2,args="王",name="2")
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    

分布式进程

  • Python的 multiprocessing模块不但支持多进程,其中 manager子模块还支持把多进程分布到多台机器上。一个服务进程作为调度者,将任务分布到其他多个进程中,依靠网络通信。

  • 服务进程

    import queue,random
    from multiprocessing.managers import BaseManager
    
    tasks_queue=queue.Queue()
    result_queue=queue.Queue()
    
    class QueueManager(BaseManager):
        pass
    
    def get_tasks_queue():
        return tasks_queue
    
    def get_result_queue():
        return result_queue
    
    if __name__=='__main__':
        QueueManager.register('get_tasks_queue',callable=get_tasks_queue)
        QueueManager.register('get_result_queue',callable=get_result_queue)
    
        manager=QueueManager(address=('localhost',5000),authkey=b'abc')
    
        manager.start()
    
        task=manager.get_tasks_queue()
        result=manager.get_result_queue()
    
        for i in range(10):
            n=random.randint(0,10000)
            print('Put task%d...' % n)
            task.put(n)
    
        print('Try get results...')
        for i in range(10):
            r=result.get(timeout=10)
            print('Result:%s' % r)
    
        manager.shutdown()
        print('master exit.')
    
  • 任务进程

    import queue
    from multiprocessing.managers import BaseManager
    
    class QueueManager(BaseManager):
        pass
    
    if __name__=='__main__':
        QueueManager.register('get_tasks_queue')
        QueueManager.register('get_result_queue')
    
        server_address='127.0.0.1'
        print('连接%s中......' % server_address)
    
        m=QueueManager(address=(server_address,5000),authkey=b'abc')
        m.connect()
    
        task=m.get_tasks_queue()
        result=m.get_result_queue()
    
        for i in range(10):
            try:
                n=task.get(timeout=1)
                print('获取%d' % n)
                r='%d * %d = %d' % (n, n, n*n)
                result.put(r)
            except queue.Empty:
                print('null')
    
        print('end...')
    

正则表达式

正则表达式

  • 匹配字符串
    • \d可以匹配一个数字
    • \w可以匹配一个字母或数字
    • .可以匹配任意字符
    • \s可以匹配一个空格或者制表符等空白字符
    • *表示任意个字符(包括0个),+表示至少一个字符,?表示0个或1个字符,{n}表示n个字符,{n,m}表示n至m个字符
  • 进阶
    • 使用 []表示范围,例如:
      • [0-9a-zA-Z\_]可以匹配一个数字,字母或者下划线
      • [a-zA-Z][0-9a-zA-Z\_]*可以匹配字母开头,后接任意个数字字母下划线组成的字符串
    • A|B可以匹配A或B
    • ^表示行的开头,^\d表示以数字开头
    • $表示行的结尾,\d$表示以数字结尾

re模块

r前缀

  • Python提供 re模块,包含所有正则表达式的功能,由于Python的字符串本身也用 \转义,所以要特别注意

    ss="pyth\\on"
    print(ss)
    
  • 使用 r前缀,就不用考虑转义的问题了

    ss=r"pyth\\on"
    print(ss)
    

Match()方法

  • match()方法判断是否匹配,匹配的话返回一个 Match的类,不匹配的话返回 None

    import re
    
    print(re.match(r'\d\w','1#'))
    print(re.match(r'\d\w','1q'))
    

切分字符串

  • 用正则表达式切分字符比用固定字符串更加灵活

    import re
    print('a b  c'.split(' '))
    print(re.split(r'\s+','a b  c')
    

分组

  • 除了简单的判断是否匹配外,正则表达式还有提取子串的功能,用 ()表示的就是要提取的分组(Group)

    import re
    
    tt=re.match(r'^(\w)(\w\w)$','陈佳浩')
    print(tt)
    
    print(tt.group(0))
    print(tt.group(1))
    print(tt.group(2))
    

贪婪匹配

  • 正则匹配默认是贪婪匹配,就是匹配尽可能多的字符,使用 ?采用非贪婪匹配

    import re
    
    m=re.match(r'^(\d+)(0*)$', '102300').groups()
    n=re.match(r'^(\d+?)(0*)$', '102300').groups()
    print(m)
    print(n)
    

常用内建模块

datetime

  • datetime是Python处理日期和时间的标准库

获取当前时间

  • datetime是模块,datetime模块还包含一个 datetime类,通过 from datetime import datetime导入的才是 datetime这个类

    from datetime import datetime
    
    now=datetime.now()
    print(now)
    
  • 如果仅 import datetime,则必须引用全名 datetime.datetime

获取指定日期和时间

  • 要指定某个日期和时间,我们直接用参数构造一个 datetime

    from datetime import datetime
    
    date=datetime(2023,12,7,22,46,30)
    print(date)
    

datetime转换timestamp

  • 在计算机中,时间实际上使用数字表示的。我们把1970年1月1日 00:00:00 UTC+00:00时区的时刻称为epoch time,记为 0(1970年以前的时间timestamp为负数),当前时间就是相对于epoch time的秒数,称为timestamp。

  • 可以认为:

    timestamp=0=1970-1-1 00:00:00 UTC+0:00
    
  • 对应的北京时间为:

    timestamp=0=1970-1-1 08:00:00 UTC+8:00
    
  • timestamp的值与时区毫无关系,因为timestamp一旦确定,其UTC时间就确定了,转换到任意时区的时间也是完全确定的

  • 把一个 datetime类型转换为 timestamp只需要简单调用 timestamp()方法:

    from datetime import datetime
    
    date=datetime(2023,12,7,22,46,30)
    print(date.timestamp())
    
  • python的timestamp是一个浮点数,整数位表示秒

timestamp转换为datetime

  • 要把timestamp转换为 datetime,使用 datetime提供的 fromtimestamp()方法:

    from datetime import datetime
    
    date=datetime(2023,12,7,22,46,30)
    tdate=date.timestamp()
    print(datetime.fromtimestamp(tdate))
    

str转换为datetime

  • 很多时候,用户输入的日期和时间是字符串,要处理时间,首先必须把str转换为datetime,转换方法是通过 datetime.strptime()实现,需要一个日期和时间的格式化字符串

    from datetime import datetime
    
    strday=datetime.strptime('2023-12-14 14:34:20','%Y-%m-%d %H:%M:%S')
    print(type(strday),strday)
    

datetime转换为str

  • 如果已经有了datetime对象,要把它格式化为字符串显示给用户,就需要转换为str,转换方法是通过 strftime()实现的,同样需要一个日期和时间的格式化字符串

    from datetime import datetime
    
    tt=datetime.now()
    strday=datetime.strftime(tt,'%Y-%m-%d %H:%M:%S')
    print(type(strday),strday)
    

机器学习

numpy库

用于高性能科学计算和数据分析,是常用的高级数据分析库的基础包


评论