文章目录
- 首先思考三个问题:
- 一.入门须知
- 二.基本概念
- 三.数值类型
- 四.条件语句
- 五.逻辑运算
- 六.while循环
- 七.for循环
- 八.break(终止),continue(跳过)
- 九.列表
- 十.元组
- 十一.字符串
- 十二.字典
- 十三.集合
- 十四.运算符的优先级
- 十五.函数
- 十六.文件
- 十七.模块
- 十八.面向对象
- 十九.继承
- 二十.异常
- 二十一.正则
首先思考三个问题:
**问题一:**我们为什么来学习Python?
**问题二:**我们要如何学好Python?
**问题三:*关于我的知识分享
我们为什么来学习Python?
1.优雅简洁
Python先对于其他的编程语言,要更加 优雅 、简洁,入门更加容易,同时语法规则更加简单明了
2.胶水语言
Python是一门胶水语言,也是一门脚本语言,Python可以很方便的和其他编程语言进行交互,可以调用其他的语言写的程序, 也可以嵌入其他语言当中去
3.运用广泛
Python在Web后台、爬虫、数据分析、机器学习、人工智能、自动化测试、自动化运维、量化交易、金融分析等方面都有很好的应用。因此学会python可以选择从事的方向非常多,这些年在金融方向上的重要性也逐年提高
4.效率高
(1)Python的开发效率高,代码量更少。同样的项目,和java相比,python的代码量可能只有Java代码的四分之一
(2)可移植性好,python本身是开源的,所以能够很快的移植到许多平台上
我们要如何学好Python?
学习需要不断的积累与操练,一切只谈方法不谈实践的方法都是纸上谈兵!
最快掌握的Python的途径就是多实践,多思考,多记笔记
关于我的知识分享
1.创一个博客,用博客分享知识
2.可以对学过的内容进行归纳总结,能够快速帮自己建立起知识体系
3.即分享了知识,也方便自己复习
4.养号,坚持分享,长期积累起来,你也能成为大佬
一.入门须知
1.python的诞生的背景
在Python之前已经诞生了非常多的编程语言,也有非常多的编程语言至今任然被广泛使用,或者是在某些特定领域发挥着重要作用,而Python的诞生充满喜剧性,同时又是时代的选择!
(1)早期编程语言的复杂性
早期编程语言基本都是面向过程的,可以简单理解为每一步都需要程序员都写出来
(2)Guido的苦恼
Guido十分苦恼于当时编程语言的复杂性和效率低下,明明逻辑清晰却要很久才行做完
(3)1989年的圣诞节
Guido在过圣诞节时忍不住自己去写一个优雅的编程语言,到1991年Python正式发布1.0版本
2.python的发展
(1)早期运用
1991年Python1.0版本正式发布,Python是用C语言写的,所以可以直接调用C库文件,还并没有广泛的流行起来
(2)开源推动
Python 2.x 社区支持,让Python快速的发展起来,2000年开始社区支持之后,Python得到了快速的发展,各种实用类型的模块快速的出现
(3)python 3.x
2008年,Python3.0正式发布,意味Python进入了一个新的时代,在Python 2.x版本中,还存在这个不少不完善的地方,因此社区推出了不是完全兼容2版本的3版本
(4)广泛流行
Python从进入社区开始,就不断在各个领域大放异彩,Python开始在:云计算、Web开发、科学计算和人工智能、系统操作和维护、金融、图形GUI等领域应用开来。
二.基本概念
1.数学计算符
+加 -减 *乘 /除 //整除 %余数 **幂指数
2.变量:
变量是编程语言中最基本的概念,和字面意思一样,指的就是他们的值可变,和我们以前学习的方程类似,变量可以代入任何值,变量帮我们减少代码的复杂性,增强可读性。
(1)命名规范
变量一般使用: 英文字母、下划线 和 数字组成,
注意:第一个字母必须是英文字母或者下划线_
支持中文作为变量名,不规范。不建议,首选英文,abcd…
关键字不能做变量名
内置函数最好也不要做变量名
(2)见明知意
程序中肯定会有很多变量名,所以变量的命名十分重要,最好做到见名知意
3.输入输出(input,print)
(1)输出print
print('Hollow word')
print('圣美最帅')
(2)输入input
注意:输入函数接收到的任何值都是一个字符串。
print('最帅的人是:', input('请输入最帅的人的名字:'))
4.注释
(1)单行注释
#号后面为注释内容
print('圣美') # 打印圣美
# 打印圣美
print('圣美')
(2)多行注释
“”" “”"或’‘’ ‘’'三引号中间为注释内容
'''打印圣美'''
print('圣美')
"""打印圣美"""
print('圣美')
(3)快速注释
python自带的编辑器(注释:alt键+3,取消注释:alt键+4)
pycharm注释方法(注释:ctrl键+/,取消注释:ctrl键+/)
三.数值类型
四个内置函数:
str() 字符串类型
int() 数字类型
float() 小数类型
bool() 布尔类型,True或False,存在即为True,不存在即为False
1.类型转换函数
整型和浮点型之间的转换:int()、float()
a = float(1)
b = int(1.53) # 非四舍五入的值,直接忽略小数位
c = float(int(1.23)) # 结果为小数1.0
字符串和数值如何转换
约束:只有数字类型的字符串才可以转换成数值类型的值
字符串转数值
a = int('1') # 字符串1转成整型
print(type(a)) #查看变量a的类型
b = float('1') # 字符串1转成浮点型
c = float('1.123')
d = int('1.55') # 字符串小数类型的值不能转整型
数值转字符串,没有约束,可以随意转换
2.字符串概念
定义:由中英文,数字,各种通用符,空格并且由引号包裹起来的这么一长串的字符组成的文本数据。字符串可以为空,也可以由多个字符组成。
引号:单引号(英文),双引号,三引号(“”" “”") ,必须成双成对。
# 字符串的运算:加、乘
# 相加(字符串+字符串) 相乘(字符串*数字),字符串的拼接。
print('5'+'8'+'同城') # 字符串相加,将多段字符串拼接在一起,成为一段字符串。
print('圣美'*3) # 字符串相乘倍数输出得到n个相同的字符串拼接成的一段字符串。
print('圣美',end='') # end连接下一行
print('*'*20,'python','*'*20,sep='') # sep将逗号产生的空格取消
3.字符串的拼接
x,y = '我喜欢', 'python'
z = '''因为我最帅'''
print(x + y + z) # + 的使用
print('%s %s %s'% (x,y,z)) # %s的使用
print(''.join([x,y,z])) # join的使用
print(f'{x}{y}{z}') # f 方法
a = "{0} {1} {2}".format(x,y,z) # format的使用
print(a)
4.字符串格式化
# %d--格式化整数
# 格式化整数时,你可以决定格式化后这个字符串的字符宽度,只需要在d前面加上宽度位数。
print('%07d'%1234) # 默认用空格去填充不足的字符宽度,也可以指定0去填充
# 左对齐-
print('%-7d'%1234)
# 右对齐+
print('%+07d'%1234)
# %f--格式化浮点数
# 默认保留6位小数,如何指定保留几位小数。
# 保留3位小数
print('%.3f'%1.2346) # 四舍五入,以6开始
# 保留2位小数
print('%.2f'%1.256)
# 保留零位(整数)
print('%.0f'%1.555) # 四舍五入,以5开始
print('%09.2f'%1.223) # 保留9位宽度,0补充
# 左对齐-
print('%-09.2f'%1.223)
# 右对齐+
print('%+09.2f'%1.223)
# 字符串的format方法
>>> '{a:.2f}'.format(a=12.3333) # 保留两位小数
'12.33'
>>> '{a:09.2f}'.format(a=12.3333) # 保留两位小数,9宽度,0补充
'000012.33'
>>> '{a:<09.2f}'.format(a=12.3333) # <左对齐
'12.330000'
>>> '{a:>09.2f}'.format(a=12.3333) # >左对齐
'000012.33'
>>> '{a:^09.2f}'.format(a=12.3333) # ^居中对齐,shift+6(英文模式下输入)
'0012.3300'
# 指定其它符号对齐
>>> '{a:*^10}'.format(a=12.3333) # 符号一定是在最前面
'*12.3333**'
>>> '{a:*<9.2f}'.format(a=12.3333)
'12.33****'
# 百分号形式输出
>>> '{}'.format(0.35) # 直接使用format拼接
'0.35'
>>> '{:.2%}'.format(0.35) # 百分号形式拼接,保留两位小数
'35.00%'
>>> '{:.0%}'.format(0.35) # 百分号形式拼接,不保留小数
'35%'
四.条件语句
1.流程控制语句(if,elif,else)
if(如果)、else(否则)、elif(否则如果)
ianqi = 'xiayu'
if tianqi == 'xiayu':
print('在家学习')
else:
print("逛街")
tianqi = 'xiayu'
if tianqi == 'yintian':
print('运动')
elif tianqi == 'xiayu':
print('在家学习')
else:
print("逛街")
注意:
if 使用:if后面更上判断表达式,注意加上冒号和缩进
else 使用:else不能单独使用,后面直接跟上冒号,没有判断式
elif 使用:elif只能跟在if后面,不能单独出现
2.三目运算
a = 6
if a > 5:
print(True)
else:
print(False)
# 等效于
print(True if a > 5 else False)
注意:只有简单if判断可以使用,过于复杂判断就不要使用了,那样会影响代码的可读性
五.逻辑运算
1.常见的判断符(比较运算符)
注意:比较运算符的返回结果都是bool型
在实际使用中,会经常用到它们,或者他们的组合
2.逻辑运算符 and or not (与,或,非) 逻辑判断
and
表示“并且”或者“和” 的意思,只有当 and 两边都是为真的时候,才会返回 真, 在其他语言中常用 & 来表示 and
or
表示“或者”的意思,只要两边存在真,就会返回真,都会假才会返回假, 在其他语言中常用 | 来表示 or
not
表示“取反”的意思,也就是真的会变成假的,假的会变成真的,在其他语言中常用 ! 来表示 not
3.逻辑短路
为了优化我们的代码而存在的,在特定的条件下不需要计算完。
逻辑运算过程中,如果已经能够得到最后的值,则不会再进行后面的判断,这个称为逻辑短路
# and逻辑短路
a=3
>>> a>4 and b>1
False
>>> a>2 and b>1
or 也存在逻辑短路,只要前面确定为True,则后面就不会再进行判断
a=3
>>> a==5 or b>1
True
>>> a<5 and b>1
六.while循环
1.while 的使用和 if 类似,判断为真的时候则运行缩进里面的代码,判断式为假时则停止循环
a = 1
while a < 5:
print(a)
a += 1
2.while 循环后面也可以接上else循环,当循环正常结束时,就会执行else 内的代码
a = 1
while a < 5:
print(a)
a += 1
else:
print('循环结束')
3.while 后面也可以直接跟上True,但是内部就必须要使用break来终止循环
a = 1
while True:
if a == 5:
break # 终止循环
print(a)
a += 1
else:
print('循环结束') # 没有执行
注意:使用break终止的循环,是不会执行else的内容
七.for循环
循环次数由数据类型的长度决定,取完数据类型里面的内容,循环就结束
for i in '圣美':
print(i)
打印了2次
for循环可以把字符串里面的每个元素都依次取出来,自动赋值给变量 i, 然后再执行循环体内的代码块
for i in range(10):
print(i, end=',') # print 里面的 end 可以设置每个值打印之后输出的字符串,默认是换行
range 函数可以取到一个范围内的整数,取值的形式为左闭右开,左取右不取,相比 while 要方便很多
八.break(终止),continue(跳过)
for循环 和 while循环中都可以使用break 和 continue
同时后面也可以接上else,当循环被break终止时,else不会执行
for i in range(1, 10):
if i % 2 == 0 or i % 2 == 3:
continue # 跳过偶数
elif i % 15 == 0:
break
else:
print(i, end=',')
else:
print('循环结束')
九.列表
可变数据类型,可以存放所有的数据类型
1.列表的定义
用方括号包裹起来的就叫做列表
list0 = []
list1 = ['西瓜','白菜','苹果',100]
print(type(list0)) # 查看数据类型
print(type(list1)) # 查看数据类型
存放数据时,要存放的数据以逗号隔开,存放好之后,你可以选择变量赋值的形式接收使用
2.列表的索引(index)取值
列表中每个元素在列表中的位置称为索引(index),可以通过索引值来取对应位置上的值
单值切片
list1 = ['西瓜','白菜','苹果',100]
>>> list1[1]
'白菜'
>>> list1[-1]
注意:
1. 索引值是从0开始
2. 负索引就是从列表尾部往前数
3. 索引取值超过长度就会报错
3.列表切片
列表还可以根据一个范围来取值,这称为切片
list1 = ['西瓜','白菜','苹果',100]
# 双值切片
print(list1[0:2]) # 取出索引0-2范围的值,冒号隔开,左闭右开形式去取值
print(list1[0:4])
# 双值切片也可以通过负索引去取值
print(list1[-3:-1]) # 左闭右开,从左往右取
# 双值切片可以超过索引范围去取值
print(list1[0:100])
#三值切片,相应的加一个步长去取值
print(list1[0:5:2]) # 左闭右开去取值
# 三值切片通过负索引去取值分两种:从右往左取和从左往右取
# 从右往左取
print(list1[-1:-4:-2]) # 大的索引在前,小的索引在后,步长为负步长(左开右闭)
# 从左往右取
# print(list1[-4:-1:2]) # 小的索引在前,大的索引在后,步长为正步长(左闭右开)
# 切片的进阶使用
# print(list1[:3]) # 从0开始取,取到3,左闭右开
# print(list1[1:]) # 从1开始取取到最后一个值,左闭右开
# print(list1[:]) # 不给指定范围取所有
# print(list1[::]) # 步长默认为1
注意:
1.切片是两个范围之间取值,且后面的数取不到
2.切片时范围超过也没有关系
3.切片时还可以指定步长
4.列表的增删改查
(1)添加:append、extend、insert 这三个方法
单个添加append() 默认添加在最后
list1 = ['西瓜','白菜','苹果',100]
list1.append('梨子')
print(list1)
批量添加extend() 默认添加在最后,以列表形式添加多个
list1 = ['西瓜','白菜','苹果',100]
list1.extend(['egg1','egg2'])
print(list1)
值定位置添加insert() 索引
list1 = ['西瓜','白菜','苹果',100]
list1.insert(1,'肉')
print(list1)
列表相加的形式去添加
list1 = ['西瓜','白菜','苹果',100]
list2 = ['鸡蛋','青椒']
list3 = list1+list2
print(list3)
注意:如果是直接两个列表相加,记得重新赋值,否则不会改变值
(2)删除:pop、remove、clear、del 这四个方法
pop 单个删除 默认从最后一个元素删除
list1 = ['西瓜','白菜','苹果',100]
a = list1.pop() # 通过pop删除的元素是可以被查看到的
print(a)
print(list1)
pop 指定索引位置删除
list1 = ['西瓜','白菜','苹果',100]
a = list1.pop(2) # 通过pop删除的元素是可以被查看到的
print(a)
print(list1)
remove 指定元素删除 默认从左往右删
list1 = ['西瓜','白菜','苹果',100,'西瓜']
list1.remove('西瓜')
print(list1)
clear 一次性清空所有元素
list1 = ['西瓜','白菜','苹果',100,'西瓜']
list1.clear()
print(list1)
del删除指定切片,默认清除全部
list1 = ['西瓜','白菜','苹果',100,'西瓜']
del(list1[:2])
print(list1)
注意:删除是不可逆的,所以删除前要确定好
(3)切片修改,重新赋值
单值切片修改
list1 = ['西瓜','白菜','苹果',100]
list1[0] = '葡萄'
print(list1)
双值切片修改 不限制元素个数
list1 = ['西瓜','白菜','苹果',100]
list1[:3] = ['美女','圣美']
print(list1)
# 双值切片删除
# list1[:3] = [] # 若为空,则会删除
# print(list1)
三值切片修改,限制元素个数,每一个元素需要一一对应
list1 = ['西瓜','白菜','苹果',100]
list1[0:4:2] = ['美女','圣美']
print(list1)
(4)查找index 根据元素,找到元素的索引值
list1 = ['西瓜','白菜','苹果',100]
list_index = list1.index('西瓜')
print(list_index)
5.列表扩展方法
(1)copy()方法
复制,在原列表的基础上复制一个新的列表,新的列表不会影响原来列表里的元素
list1 = [2,3,4,5,6,7,8,8,3]
a = list1.copy()
a[0] = 1
print(list1)
print(a)
(2)id()函数
内存函数,查看数据类型的存储地址
list1 = [2,3,4,5,6,7,8,8,3]
a = list1.copy()
a[0] = 1
print(id(list1))
print(id(a))
(3)count()统计
统计元素个数,出现的次数
list1 = [2,3,4,5,6,7,8,8,3,2,2]
num = list1.count(2)
print(num)
(4)reverse()倒序
反向输出一个列表,会修改原列表的表结构
list1 = [2,3,4,5,6,7,8,8,9,0]
list1.reverse()
print(list1)
(5)排序:sorted(临时排序)和sort(永久排序)
sorted() 对列表进行排序,默认升序,不会修改原列表,降序排序加入参数reverse=(True降序或False升序)
list1 = [2,3,4,5,6,7,8,8,9,0]
a = sorted(list1, reverse=True) # 降序
print(list1)
print(a)
sort() 对列表进行排序,默认升序,会修改原列表,降序排序加入参数reverse=(True降序或False升序)
list1 = [2,3,4,5,6,7,8,8,9,0]
list1.sort(reverse=True) # 降序
print(list1)
6.列表推导式
结合for循环快速生成一个列表
【如何在100以内得到所有偶数,将所有的偶数存放在一个列表list_a里面】
list_a = []
for i in range(101):
if i % 2 == 0: # 偶数
list_a.append(i)
print(list_a)
# 列表推导式公式
a = [i for i in range(101) if i % 2 == 0]
print(a)
十.元组
不可变数据类型,不可以被修改,只能进行查找操作。
1.元组的定义
类似列表,也可以索引取值,但是元素不能更改,一旦确定,就无法改变
tup0 = ()
tup1 = (20, )
tup2 = (20) # 这不是元组
print('tup0 =',type(tup0)) # 查看数据类型
print('tup1 =', type(tup1)) # 查看数据类型
print('tup2 =', type(tup2)) # 查看数据类型
注意:如果元组只有一个元素,还是要跟上逗号“,”,否则会当作一个元素,而不是元组
2.元组切片取值
tup1 = (20, '圣美','python','java',10,(2,2),[1,2])
tup2 = (0, '姑娘')
print(tup1[:3])
print(tup1[0:5:2])
print(tup1+tup2)
3.元组不能增、删、改
4.拆包:
将元组里面的元素拆分给多个变量去使用,变量个数不超过元组长度
tup = (1,2,3,4,5)
a,b,c,d,e = tup
print(a)
print(b)
print(c)
print(d)
print(e)
拆包时还可以选择变量前面加上* 号去接收,这种加上*特殊定义的变量就是用来一次性接收多个
tup = (1,2,3,4,5)
a,*b,c = tup
print(a)
print(*b) # 若不加*号返回的是一个列表
print(c)
十一.字符串
不可变数据类型,不可以被修改,只能进行查找操作。
1.字符串的修改
注意:字符串和列表不同,不能修改,通常称为字符串的不可变
如果需要修改字符串,那么需要调用字符串内置的方法并且重新赋值
(1)replace()方法修改替换
replace方法默认替换所有字符元素
str_a = 'this is python string'
# replace方法修改替换
str_a = str_a.replace('i', 'I') # replace方法默认替换所有字符元素
print(str_a)
replace方法指定替换次数
str_a = 'this is python string'
# replace方法指定替换次数
str_a = str_a.replace('is', 'I', 1) # replace方法默认替换所有字符元素
print(str_a)
(2)upper()方法全部大写
str_a = 'this is python string'
# upper方法大写
str_a = str_a.upper() # 全变成大写
print(str_a)
(3)lower()方法全部小写
str_a = 'THIS IS PYTHON STRING'
# lower方法小写
str_a = str_a.lower() # 全变成小写
print(str_a)
(4)capitalize()方法首字母大写
str_a = 'this is python string'
# capitalize方法首字母大写
str_a = str_a.capitalize() # 首字母大写
print(str_a)
(5)title()方法每个单词的首字母大写
str_a = 'this is python string'
# title方法每个单词的首字母大写
str_a = str_a.title() # 标题形式
print(str_a)
(6)strip()去掉字符串两边空格
lstrip()去掉字符串左边空格
rstrip()去掉字符串右边空格
str_a = ' this is python string '
# strip去掉字符串两边空格
str_a = str_a.strip() # 去掉字符串两边空格
print(str_a)
2.字符串的查找index()方法
(1)默认查找,找不到会报错
str_a = 'this is python string'
b =str_a.index('i')
print(b)
(2)指定起始位置查找,找不到会报错,超出会报错
str_a = 'this is python string'
b =str_a.index('i', 40) # 包括当前索引位置
print(b)
3.字符串的查找find()方法
find 和index类似,可以找到元素在字符串中的索引值,也可以指定其它的查找位置,但是如果找不到元素,不是报错,而是返回-1
(1)默认查找,找不到元素不报错而是返回-1,超出索引找不到索引也是返回-1
str_a = 'this is python string'
b =str_a.find('i') # 找不到元素不报错而是返回-1,超出索引找不到索引也是返回-1
print(b)
(2)指定起始位置查找,找不到元素不报错而是返回-1,超出索引找不到索引也是返回-1
str_a = 'this is python string'
b =str_a.find('i', 5) # 包括当前索引位置
print(b)
4.字符串的一些判断方法
注意:返回值为True或False
(1)isalpha()判断是否全是字母,中文也算字母
str_a = '圣美'
b = str_a.isalpha() # 判断是否全是字母,中文也算字母
print(b)
(2)isdigit()判断是否全是数字
str_a = '圣美1号'
b = str_a.isdigit() # 判断是否全是数字
print(b)
(3)islower()判断是否全是小写
str_a = 'asdfg'
b = str_a.islower() # 判断是否全是小写
print(b)
(4)isupper()判断是否全是大写
str_a = 'asdfg'
b = str_a.isupper() # 判断是否全是大写
print(b)
5.字符串切割
注意:对字符串进行切割,默认是以空格来作为分割符,切割之后的元素会放在一个列表当中
(1)split()切割
默认空格切割
str_a = 'this is python string'
b = str_a.split() # 默认空格切割
print(b)
指定字符切割
str_a = 'this is python string'
b = str_a.split('i') # 指定’i‘切割
print(b)
指定切割次数
str_a = 'this is python string'
b = str_a.split('i', 2) # 指定’i‘切割,切割次数为2
print(b)
(2)join()拼接
通常切割之后,对每个字符串处理完成之后,我们会再利用join拼接起来
str_a = 'this is python string'
b = str_a.split('i', 2) # 指定’i‘切割,切割次数为2
c = ','.join(b) # 返回的是一个字符串
print(c)
6.字符串转义
某些符号在字符串当中有着特殊的意义,比如
(1)\n 换行符
print('圣美\n好帅哦') # \n 换行符,在字符串当中起一个换行的作用
(2)\t 横向制表符
print('学号\t姓名\t语文\t数学\t英语')
print('111\t圣美\t10\t20\t21') # \t 横向制表符,使字符串水平对齐,默认以八个空格进行对齐
(3)\ 连接符
print\
('圣美好帅哦') # 在关键字后面加上反斜杠 \ ,将下面的与上面的连接
(4)取消转义(\和r)
转义反斜杆,在转义符的前面再加上一个,取消转义符的功能。
转义符可以来表示不方便打印的字符串,同时 r 可以去掉转义,在表示路径的时候会更加的方便
print('圣美\\n好帅哦') # 在转义符的前面再加上一个\,取消转义符的功能。
r 取消转义符
print(r'圣美\n好帅\t哦') # r 取消转义符
7.字符串编码
bytes类型
(1)encode() 编码,默认以utf-8
name = '圣美'.encode(encoding='gbk') # encode编码,以gbk的格式编码,默认是以utf-8的格式
print(name)
print(type(name)) # 查看数据类型
(2)decode() 解码,默认以utf-8
name = b'\xca\xa5\xc3\xc0'
a = name.decode(encoding='gbk') # decode解码,以utf-8的格式解码,默认是以utf-8的格式
print(a)
print(type(a)) # 查看数据类型
十二.字典
可变数据类型,能够将两个信息捆绑,关联起来
1.字典的定义
字典就是大括号{}包裹起来的,因为数据结构不同,字典是以键值对的形式进行存储
以键值对的形式进行存储,每个键对应一个值,中间用冒号进行联系,每个要存的键值对以逗号进行分割
dict0 = {}
dict1 = {'1号': '圣美', '2号': '美女', '3号': '姑娘'}
print(type(dict0)) # 查看数据类型
print(type(dict1)) # 查看数据类型
注意:键唯一,并且只能够是字符串或是数值,值可以多变,可以是任何数据类型
2.字典的取值
访问字典数据,通过键取出值,不是使用索引取值,而是直接通过键取值。
dict1 = {'1号': '圣美', '2号': ('漂亮的', '美女', 666), '3号': ['好看的', '姑娘']}
print(f"1号是:{dict1['1号']}") # 如果key不存在则会报错
通过get方法来取值,如果key不存在也不会会报错
dict1 = {'1号': '圣美', '2号': ('漂亮的', '美女', 666), '3号': ['好看的', '姑娘']}
print(dict1.get('0号', '没有这个key')) # 通过get方法来取值,如果key不存在也不会会报错,默认返回一个None 空值,这里返回 没有这个key
3.字典的增、删、改
注意:
字典是可变数据类型,字典里面的数据可以被修改,所以我们可以进行增删改操作
字典是无序的,也没有索引下标,所以访问时通过键访问值,所以无查找操作。
(1)添加
直接添加
dict_a = {}
dict_a['name'] = '圣美' # 简单添加
print(dict_a)
update()方法
dict_a = {}
dict_a.update({1: 200, 2: 100}) # 批量添加,无则增,有则改
print(dict_a)
setdefault()方法
dict_a = {}
dict_a.setdefault('name', '圣美') # 无则增,有则查
print(dict_a)
(2)删除
pop()方法
dict_a = {'a':1,'b':2,'c':3,'d':4,'e':6}
a = dict_a.pop('a') # 指定key删除键值对
print(dict_a)
popitem()方法
dict_a = {'a':1,'b':2,'c':3,'d':4,'e':6}
a = dict_a.popitem() # 随机删除一个键值对
print(f'删除的键值对是:{a}')
print(dict_a)
clear()方法
dict_a = {'a':1,'b':2,'c':3,'d':4,'e':6}
a = dict_a.clear() # 清空所有
print(dict_a)
del()方法
dict_a = {'a':1,'b':2,'c':3,'d':4,'e':6}
del(dict_a['a']) # 指定key删除键值对
print(dict_a)
(3)修改
直接修改
dict_a = {'a':1,'b':2,'c':3,'d':4,'e':6}
dict_a['a'] = 100 # 单个修改
print(dict_a)
update()方法
dict_a = {'a':1,'b':2,'c':3,'d':4,'e':6}
dict_a.update({'a': 200, 'b': 100}) # 批量修改键值对,有则改,无则增
print(dict_a)
4.字典的查找
setdefault()方法
dict_a = {'a':'圣美','b':2,'c':3,'d':4,'e':6}
a = dict_a.setdefault('a') # 有值就返回,无值则添加
print(a)
get()方法
dict_a = {'a':'圣美','b':2,'c':3,'d':4,'e':6}
a = dict_a.get('a') # 通过get方法来取值,如果key不存在也不会会报错
print(a)
5.字典的其他方法
(1)keys()方法
dict_a = {'a':'圣美','b':2,'c':3,'d':4,'e':6}
for i in dict_a.keys(): # keys方法获取字典每一个键
print(i)
(2)values()方法
dict_a = {'a':'圣美','b':2,'c':3,'d':4,'e':6}
for i in dict_a.values(): # values方法获取字典的每一个值
print(i)
(3)items()方法
dict_a = {'a':'圣美','b':2,'c':3,'d':4,'e':6}
for i in dict_a.items(): # items方法获取字典的所有键值对
print(i)
(4)copy()方法
dict_a = {'a':'圣美','b':2,'c':3,'d':4,'e':6}
dict_b = dict_a.copy()
print(id(dict_a)) # 查看dict_a的id地址
print(id(dict_b)) # 查看dict_b的id地址
(5)sorted()方法
dict_a = {'a':1,'b':2,'c':3,'d':4,'e':6}
dict_b = sorted(dict_a, reverse=True) # 降序,只排序键,组成一个列表
print(dict_b)
十三.集合
可变数据类型,和字典一样,通过大括号{}包裹起来的,不存放值,只有键
集合也是唯一且无序,没有查找操作
1.集合定义
集合也是使用大括号,但不是键值对形式,是单个元素形式
set0 = {} # 不是集合,是一个空字典
set1 = {1, 2, 3, 4, 5, 6}
a = set() # 创建空集合
print(type(set0)) # 查看数据类型
print(type(set1)) # 查看数据类型
print(type(a)) # 查看数据类型
集合具备自动去重
set1 = {1, 2, 3, 4, 5, 6, 1, 1, 5, 3, 4} # 自动去重
print(set1)
2.添加
(1)add()方法
set1 = {1, 2, 3, 4, 5, 6}
set1.add(0) # 单个添加
print(set1)
(2)update()方法
set1 = {1, 2, 3, 4, 5, 6}
set1.update({0, 7, 8, 9}) # 批量添加
print(set1)
2.删除
(1)pop()方法
set1 = {1, 2, 3, 4, 5, 6}
set1.pop() # 随机删除
print(set1)
(2)remove()方法
set1 = {1, 2, 3, 4, 5, 6}
set1.remove(1) # 指定元素删除
print(set1)
(3)clear()方法
set1 = {1, 2, 3, 4, 5, 6}
set1.clear() # 清空所有
print(set1)
3.集合的运算
(1)交集 &
set1 = {1, 2, 3, 4, 5, 6}
set2 = {'a', 'b', 'c'}
print(set1 & set2) # 取出两个集合中相同的元素,没有用一个空集合:set() 表示
(2)并集 |
set1 = {1, 2, 3, 4, 5, 6}
set2 = {'a', 'b', 'c'}
print(set1 | set2) # 合并两个集合去掉重复元素
(3)差集 -
set1 = {1, 2, 3, 4, 5, 6}
set2 = {4, 5, 'a', 'b', 'c'}
print(set1 - set2) # 取出set1有的,set3没有的元素
4.集合的判断
(1)isdisjoint()方法
set1 = {1, 2, 3, 4, 5, 6}
set2 = {1, 2, 3}
print(set1.isdisjoint(set2)) # # 判断两个集合是否没有交集
(2)issubset()方法
set1 = {1, 2, 3, 4, 5, 6}
set2 = {1, 2, 3}
print(set1.issubset(set2)) # 判断前面的集合是否被包含在后面的集合中
十四.运算符的优先级
从搞到低
十五.函数
1.函数的定义
函数就是用来存储代码的,封装在函数里面的代码叫做函数体。
函数的格式
定义好函数后可不断调用函数,实现代码的复用性
def fun_1(shen): # 驼峰命名法
if shen:
print("这是一个帅哥")
else:
print("啥都不是")
fun_1('圣美') # 通过调用函数名向里面传入参数执行函数体使用
fun_1('圣美')
注意:函数不会影响代码的运行,函数只有在调用的时候才会去执行,并且函数在任何条件下都可以去调用
2.函数的调用
直接函数名加括号就是在调用函数,函数在调用时会执行函数里面的函数体
def fun():
print("圣美又变帅了")
fun() # 调用函数
注意:
函数调用时一定要函数名加括号去调用
无括号是只是调用函数体,而没有去执行函数体
函数调用中的return
print并不能将打印的内容作为函数的返回值,赋值给变量使用
def func(a, b):
num = a+b
print('相加结果为:', num) # print只是单纯的执行了一个打印的效果。并不能将打印的内容作为函数的返回值,赋值给变量使用。
print(func(1,2))
使用关键字return
def func(a, b):
num = a+b
return '相加结果为:', num # return返回多个值时是一个元组类型的数据
print(func(1,2))
return的作用:
作用1、函数在调用后拥有一个返回值
作用2、return 的执行表示函数的结束
注意:return后面不写值同样返回的是空值
3.函数的参数
Python中函数主要有这四种参数:
必备参数、关键字参数、默认参数 和 不定长参数
其中不定长参数有:元组和字典两种类型
(1)必备参数:
调用时必须要传的参数
def func(name, age):
print(f'{name}{age}岁')
func('圣美', 18)
(2)关键字参数:
指定参数来进行传参
def func(name, age):
print(f'{name}{age}岁')
func(age=18, name='圣美')
注意:必备参数和关键字参数同时使用,必备参数一定是在关键字参数前面
(3)默认参数 :
调用可以不传入,不传入时默认使用默认值
def func(name, age=20): # 对age设置默认值,默认20
print(f'{name}{age}岁')
func(name='圣美', age=18)
func(name='美女')
(4)不定长参数:
可以传入也可以不传入,不传入时默认为空元组和空字典
一个星号(元组不定长参数)和两个星号(字典不定长参数)
def func(name, age=20, *args, **kwargs): # 必备参数-默认参数-元组不定长-字典不定长
print(f'{name}{age}岁')
print(args)
print(kwargs)
func('圣美', 18, 'a', 'b', 'c', 圣美=18, 姑娘=20, 美女=21)
注意:字典传入是,必须是键值对的形式,且只能最后传入,定义时也只能放在最后面
4.函数的作用域
(1)全局变量:
在函数外面定义的叫全局变量,全局变量不管是函数内还是函数外都能够被调用使用
num1 = 20 # 全局变量
def func2():
print(num1) # 全局变量在函数里面调用不会报错
func2()
print(num1)
(2)局部变量:
定义在函数里面的叫局部变量,局部变量只能够在函数里面调用,函数外面无法调用局部变量去
def func2():
num2 = 30 # 局部变量
print(num2)
func2()
print(num2) # 函数外面无法使用num2,会报错
(3)全局作用域:
如果想要在函数内修改全局变量的值就必须使用global 关键字进行变量声明
num1 = 20 # 全局变量
def func2():
global num1 # 声明全局变量
num1 = num1+1 # 函数内部不可以对全局变量进行修改
print(num1)
func2() # 先调用在打印
print(num1)
(4)局部作用域:
局部变量在什么时候不可以被修改,函数的嵌套
def func(): # 外层函数
num2 = 30 # 局部变量
def func1():
nonlocal num2 # 声明局部变量
num2 = num2+1
print('func1',num2)
def func2():
print('func2',num2)
return func1, func2 # 返回内层函数的函数体
a,b = func() # a赋值的就是内部的函数体 func1
a() # 对内部函数执行:func1()
b() # 对内部函数执行:func2()
注意:如果是嵌套的函数,则不能使用global,需要使用nonlocal 关键字,未声明时会报错
(5)闭包:
外层函数返回内层函数的函数体,供外部接受使用
def func(): # 外层函数
num2 = 30 # 局部变量
def func1():
nonlocal num2 # 声明局部变量
num2 = num2+1
print('func1',num2)
def func2():
print('func2',num2)
return func1, func2 # 返回内层函数的函数体
a,b = func() # a赋值的就是内部的函数体 func1
a() # 对内部函数执行:func1()
b() # 对内部函数执行:func2()
5.递归函数
函数自身调用自己,也需要一个结束条件,否则超出递归深度就会报错
def rec(n):
if n<=1:
return 1
else:
return n * rec(n-1) # 5*4*3*2*1=120
print(rec(5))
6.匿名函数
匿名函数就是没有函数名的函数,主要用来定义那种不是特别复杂的函数,常用于函数的参数中
匿名函数表达式:函数名 = lambda 参数:对参数做的操作
def g(x, y):
return x+y
g(2)
等效于:
# 使用lambda去定义一个匿名函数,对简单的函数进行简化
g = lambda x: x+1 # 冒号后面是匿名函数的返回值
print(g(2))
进行多个传参使用
g = lambda x, y: x+y # 冒号后面是匿名函数的返回值
print(g(1, 4))
列表排序使用匿名函数 lambda
li = [2, 'a', 1, 's', 'z', 0]
li.sort(key=lambda x: str(x)) # x参数来自列表的每一个元素
print(li) # lambda不会修改原列表的值,只是临时修改去做一个sort排序
a = sorted(li, key=lambda x: str(x), reverse=True) # 也可以加入升降序操作
print(a)
7.回调函数
在函数里面对于其它函数的调用
def shen():
print('圣美', end='')
def chi(a):
a() # 对传入的函数shen的调用
print('会吃饭')
chi(shen)
8.函数注释 ->
def fun(a) -> '返回的是字符串': # -> 函数注释方法
return str(a)
b = fun('圣美又变帅了') # 调用函数
print(b)
十六.文件
文件 .txt .docx .py 有标识后缀的,音频图像 .png .mp4
1.基本操作
两种路径:
绝对路径:从盘符开始的路径
相对路径:就是你当前执行py脚本所在的路径
# 绝对路径
open('D:\python程序\student\圣美.txt') # 加上第一个参数,打开 圣美.txt 这个文件
# 相对路径
file_one = open('圣美.txt') # 加上第一个参数,打开 圣美.txt 这个文件
print(file_one) # 文件对象
没有则会报错
(1)open函数
open(打开的文件,打开的模式,打开的格式)
打开的文件: 就是你要操作的文件,具体的文件路径,文件的后缀一定要加上
打开的模式: 读写和追加,也就是你想对文件做何种操作
常用模式有:
r 只读
w 只写,每次打开会清空之前的内容,如果打开的文件不存在,则会自动创建这个文件
a 追加,如果文件不存在,也会自动创建文件,之后再去写入内容
b 二进制打开
+ 更新(读和写),使w和a有了读取的功能,r有了写入的功能
打开的格式: 以何种编码格式去打开这个文件去做操作,一般使用的是'utf-8'这种编码格式
flush()直接保存
close()关闭并保存
write()单行写入
writelines()多行写入
read()读取指定字符,默认读取全部
readline()读取一行
readlines()读取多行
tell()获取光标位置
seek()调整光标位置
# 文件 w 操作
file_one = open('圣美.txt', 'w', encoding="utf-8") # w 创建 圣美.txt 文件
file_one.write('圣美是个帅哥') # 单行写入
file_one.writelines(['第一个内容\n', '第二个内容\n']) # 多行写入
# 注意:操作完成之后,一定要保存或关闭
# file_one.flush() # flush直接保存
file_one.close() # close关闭并保存
# # 文件 a 操作
# file_a = open('圣美.txt', 'a', encoding="utf-8") # a 追加,如果文件不存在,也会自动帮我们创建文件,之后再去写入内容
# file_a.write('圣美喜欢姑娘') # 与w的区别就是,w会清空之前的内容再写入,a会直接追加在原来的内容后面
# file_a.close() # 完成追加后,close关闭文件
# 文件 r 读操作
file_two = open('圣美.txt', 'r', encoding='utf-8') # 读取圣美.txt
file = file_two.read(3) # 指定读取几个字符,默认读取全部
# file = file_two.readline() # 读取一行
# file = file_two.readlines() # 读取多行,反馈出一个列表对象
print(file)
# 当文件读取之后,可以调用tell方法查看文件中指针的位置
zhi = file_two.tell() # 查看指针的位置
print('指针位置在:', zhi)
# 当指针在末尾时读取不出内容,需要用seek把指针移动到文件开头
zhi_1 = file_two.seek(0) # 将指针移动到0处
print('指针位置在:', zhi_1)
file_one.close() # 完成操作后,close关闭文件
(2)with open()持久化存储,不需要手动close
每次打开文件都需要再次关闭,但是如果使用with 可以自动关闭文件,不需要手动关闭
with open('圣美.txt', 'r', encoding="utf-8") as f: # 加上 with 可以自动关闭文件,不需要手动关闭
file = f.read() # 读取全部
print(file)
2.文件流
在内存中打开一个文件流,如同打开一个文件
(1)字符流
import io # 导入文件流模块 io
# 字符流
string_io = io.StringIO()
string_io.write('圣美') # 写入
a = string_io.getvalue() # 读取操作,getvalue方法可以获取内容
print(a)
string_io.close() # 销毁
(2)字节流
import io # 导入文件流模块 io
# 字节流
bytes_io = io.BytesIO()
bytes_io.write(b'asdfg') # 字符串前面加b,标识这是一个二进制的字符串数据,主要用来存储图像、音频、视频等
a = bytes_io.getvalue() # 读取操作,getvalue方法可以获取内容
print(type(a)) # 字节类 bytes 二进制数据
print(a)
bytes_io.close() # 销毁
3.文件的目录操作
文件目录操作(文件夹)和操作系统交互,类似终端
>>> import os # 导入操作系统模块
>>> os.getcwd() # 获得当前路径
>>> os.chdir(r'D:\python程序') # 切换路径
>>> os.listdir(path='圣美.txt') # 查看文件和子目录,默认是当前目录
>>> os.mkdir(r'D:\python程序\student\圣美') # 创建文件夹,已经有了就不能继续创建
>>> os.makedirs(r'aa\bb') # 在当前路径下,创建多层文件夹
>>> os.remove('test.txt') # 删除文件,删除时里面不能有其他的文件或文件夹
>>> os.rmdir(r'D:\python程序\student\圣美') # 删除一层文件夹,删除时里面不能有其他的文件或文件夹
>>> os.removedirs(r'aa\bb') # 删除多层文件夹,删除时里面不能有其他的文件或文件夹
>>> os.system('cmd') # 调用系统命令
>>> os.walk(r'D:\python程序') # 遍历当前文件下面的所以文件及子目录
>>> os.path.join('aa', 'bb') #拼接路径 aa\bb
十七.模块
Python中的模块,指的就是一个py文件,模块在导入时,会自动执行一遍
from datetime import datetime as dt # as可以给导入的内容来重新命名
print(dt.now())
1.datetime日期-时间 模块
from datetime import datetime, date # 使用from来导入datetime中的datetime, date内容
print(date.today()) # 获得当前日期
print(datetime.now()) # 获得当前日期,包括时分秒
(1)strptime() 将字符串时间数据转成时间类型数据
from datetime import datetime
string = '2022-05-05 20:50:40'
# %Y-%m-%d(年-月-日) %H:%M:%S(时-分-秒)
time1 = datetime.strptime(string, '%Y-%m-%d %H:%M:%S')
print(time1)
print(type(time1))
(2)strftime() 将时间类型数据转成字符串
from datetime import datetime
# %Y-%m-%d(年-月-日) %H:%M:%S(时-分-秒)
time1 = datetime.now()
time2 = datetime.strftime(time1,'%Y-%m-%d %H:%M:%S') # 不做限制
print(time2)
print(type(time2))
2.time 时间模块
(1)time() 获得当前时间戳
from datetime import datetime
import time # 时间模块
time1 = time.time() # 获得当前时间戳,格林威治时间1970年01月01日00时00分00秒一直到至今的总秒数
print('时间戳:', time1)
# datetime的fromtimestamp方法将时间戳转换成具体的时间
a = datetime.fromtimestamp(time1)
print(a)
print(type(a))
(2)sleep() 休眠方法
import time
time1 = time.time() # 获得程序开始时间
time.sleep(3) # 休眠3秒
print('圣美有点帅')
time2 = time.time() # 获得程序结束时间
print('运行所用时间:', time2-time1) # 看数据处理的速度,一般时间漂浮不大
3.sys 环境路径模块
# 不让其它代码在导入我们的模块时执行它里面的语句,自身运行时是会去执行的
if __name__ == '__main__':
print('这是我们的main')
十八.面向对象
概念:
将某一类事物相关的属性和方法封装在一起,用来表示这类事物
用面向对象的思维去解决问题
1.面向对象的介绍
就是对函数和变量进行封装,来提高代码的复用性
class Person: # 用关键字 class 定义的代码块称为 类
name = '圣美' # 在类里面的变量称为 类的属性
def xue(name): # 在类里面的函数称为 类的方法
print(f'{name}在学习')
def gn(name): # 方法
print(f'姑娘在看{name}')
Person.name #得到类的属性,类里面的属性不可以直接在外面调用
Person.gn(Person.name) # 调用类的方法,同时使用的是全局变量name
# 临时添加一个属性
# Person.age = 18
# 对原来的属性进行修改,临时,对原来的属性重新赋值即可
# Person.name='美女'
通过这样的封装,把和人相关的变量、函数等放在了一起,只要找到这个部分代码,就能知道关于人已经定义了哪些变量和函数
面向对象和面向过程的对比
2.类的定义和使用
class Person: # 人类
name = '圣美' # 静态属性
def __init__(self, name, age, sex): # __init__ 是初始化函数,在实例化时会自动的调用,帮我们解决属性冲突的问题
# 加入属性,假如属性一开始已经定义好了,那么它将重新赋值为新的属性值
self.name = name # bd.name = '圣美' 属性的添加
self.age = age # bd.age = 18
self.sex = sex # bd.sex = sex
# 实例化后记得为所有的方法加上self,加在参数的第一位,告诫我们方法是属于某个人独有的
def xue(self, name): # 方法 self指的是实例化对象本身 self=a
print(f'{name}在学习')
def gn(self, name):
print(f'姑娘在{name}')
def __del__(self): # 析构函数,当删除实例的时候,就会调用此方法
print('已删除了')
# 实例化对象,为初始化函数传入相应的参数值作为属性值引用
a = Person('圣美', 18, '男') # 实例化对象 实例化成 a 这个具体的人
b = Person('美女', 20, '女') # 实例化的第二个人, b 这个的人
a.xue('圣美')
b.gn('美女')
del a # 删除 a ,析构函数在删除实例对象时会自动调用一次
3.常用的内置函数
(1)hasattr 判断属性是否存在
class Person:
def __init__(self, name):
self.name = name
def xue(self):
print(f"{self.name}在学习")
a = Person('圣美')
# 注意:属性名需要加上引号
print('hasattr:', hasattr(a, 'name')) # 判断属性是否存在
# print('getattr:', getattr(a, 'name')) # 得到属性值 , 没有则报错
# print('setattr:', setattr(a, 'name1', '美女')) # 设置属性值,修改,无则增,有则改
# print('delattr:', delattr(a, 'name')) # 删除属性值
(2)getattr 得到属性值,没有则报错
class Person:
def __init__(self, name):
self.name = name
def xue(self):
print(f"{self.name}在学习")
a = Person('圣美')
# 注意:属性名需要加上引号
# print('hasattr:', hasattr(a, 'name')) # 判断属性是否存在
print('getattr:', getattr(a, 'name')) # 得到属性值 , 没有则报错
# print('setattr:', setattr(a, 'name1', '美女')) # 设置属性值,修改,无则增,有则改
# print('delattr:', delattr(a, 'name')) # 删除属性值
(3)setattr 设置属性值,修改,无则增,有则改
class Person:
def __init__(self, name):
self.name = name
def xue(self):
print(f"{self.name}在学习")
a = Person('圣美')
# 注意:属性名需要加上引号
# print('hasattr:', hasattr(a, 'name')) # 判断属性是否存在
# print('getattr:', getattr(a, 'name')) # 得到属性值 , 没有则报错
print('setattr:', setattr(a, 'name1', '美女')) # 设置属性值,修改,无则增,有则改
# print('delattr:', delattr(a, 'name')) # 删除属性值
(4)delattr 删除属性值
class Person:
def __init__(self, name):
self.name = name
def xue(self):
print(f"{self.name}在学习")
a = Person('圣美')
# 注意:属性名需要加上引号
# print('hasattr:', hasattr(a, 'name')) # 判断属性是否存在
# print('getattr:', getattr(a, 'name')) # 得到属性值 , 没有则报错
# print('setattr:', setattr(a, 'name1', '美女')) # 设置属性值,修改,无则增,有则改
print('delattr:', delattr(a, 'name')) # 删除属性值
(5)issubclass 判断第一个类是不是后面类的子类
class Person:
def __init__(self, name):
self.name = name
def xue(self):
print(f"{self.name}在学习")
a = Person('圣美')
print('issubclass:', issubclass(Person, object)) # 判断第一个类是不是后面类的子类
(6)isinstance 判断实例是否是后面的实例
class Person:
def __init__(self, name):
self.name = name
def xue(self):
print(f"{self.name}在学习")
a = Person('圣美')
print('isinstance:', isinstance(a, Person)) # 判断实例是否是后面的实例
print('isinstance:', isinstance('a', (int, str))) # 判断数据类型是否属于后面数据类型中的一种
print('isinstance:', isinstance(a, (Person, object))) # 判断实例是否是后面的实例
(7)type 只能判断单个类
class Person:
def __init__(self, name):
self.name = name
def xue(self):
print(f"{self.name}在学习")
a = Person('圣美')
# 注意:type只能判断单个类
print(type(1) == int) # 判断数据类型是否为一类
print(type(a) == Person) # 判断实例对象是否有Person产生
4.属性调用过程
class Person:
def __init__(self, name):
self.name = name
def xue(self):
print(f"{self.name}在学习")
def __getattr__(self, age): # 属性不存在时会自动执行一遍
print(f'{age}属性不存在')
# 这里调用了一些内置的方法,也会有同样的效果
# 这是因为那些函数本身就是调用的这些方法
a = Person('圣美')
a.__getattribute__('name') # 得到属性值
a.__setattr__('name1', '美女') # 设置属性值
a.__delattr__('name1') # 删除属性值
a.__init__ # 初始化方法
a.__del__ # 析构
5.魔法方法
Python中很多内置方法都是两个下划线在两边,中间是单词名字,并且这样的方法名字有一定的特殊的含义,把这种方法都称之为魔法方法
__new__方法
会在初始化之前自动调用
可以很方便的去实现一个类的单例模式:就是类始终只有一个实例存在,不会同时出现多个实例
class Person:
def __new__(obj,*args,**kwargs): # object类中的new方法是用于生成实例对象的
print('这是new实例方法')
## return super().__new__(obj)
return object.__new__(obj) # 直接引用父类的new方法帮助我们去生成实例化对象
def __init__(self,name,age): # 实例化一个对象之后才会去调用
print('init已被调用')
self.name = name
self.age = age
a = Person('圣美',18)
str : 修改print打印时的样子 repr : 修改直接打印时的样子
class Person:
def __init__(self, name):
self.name = name
def eat(self):
print(self.name+'在吃饭')
def __str__(self): # print输出实例对象会自动执行
return f'这个是{self.name}的str魔法方法'
def __repr__(self): # 直接调用实例对象会自动执行
return f'这个是{self.name}的repr魔法方法'
def __call__(self, x, y):
return x+y
a = Person('圣美')
print(a)
# print(a(1, 2)) # 就像函数一样可以去调用
6.协议
Python中有很多的协议,比如序列协议等很多协议,只要遵守这些协议,既可以说是对应的类型,比如定义了序列类型协议,则定义的类就是序列类型
(1)序列协议
即定义:len, getitem,setitem,__delitem__等协议,如果不需要改变,那后两个就不要定义
class IndexTuple:
def __init__(self, *args):
self.values = args # 元组 (1,2,'a','b')
def __len__(self): # 得到元组长度
return len(self.values)
def __getitem__(self, key): # key为下标索引
return self.values[key]
def __repr__(self): # 输出魔法方法,只能字符串形式的数据
return str(self.values)
my_t = IndexTuple(1, 2, 'a', 'b')
print(my_t)
print(len(my_t))
print(my_t[0])
(2)迭代器协议
如果类实现了__iter__ 和 next 方法,则这个类就是迭代器,因此只要实现这两个方法,则是可以迭代对象
# 将类变成一个迭代器对象
class Number:
def __init__(self, end=6):
self.start = 0 # 开始
self.end = end # 结束
def __iter__(self): # 将类变成一个迭代器对象
return self
def __next__(self):
self.start += 1 # 每次next取值就加一
if self.start <= self.end:
return self.start # 满足条件返回值
else:
raise StopIteration # 主动抛出一个错误
nu = Number()
print('iter:', iter(nu))
print('next:', next(nu))
for i in nu:
print(i)
(3)上下文协议
只要类里面定义__enter__和__exit__这两个方法,则可以使用with去使用此对象
# 上下文协议 计时器,用于测试代码运行时间
import time
class RunTime:
def __enter__(self):
self.start = time.time() # 获得时间戳,当前代码开始时间
return self.start
def __exit__(self, exc_type, exc_val, exc_tb): # 固定三个参数用于接收报错
self.end = time.time() # 代码结束时间
print('代码的运行时间为:', self.end-self.start)
# 使用
with RunTime():
for i in range(10000000):
pass
with RunTime():
for i in range(1000000000):
pass
7.生成器
【生成器(函数)】等同于 【迭代器(类)】 next() 取值 yield关键字
利用 yield 可以将一个函数变成一个迭代器
yield 具有和return一样的功能,可以返回值,同时也会暂停函数的执行,直到下一次next执行,才会继续往下运行
def fibona(end): # 定义一个斐波那契数列数列,就是前两个数相加等于后面一个数
n, a, b = 0, 0, 1
while n < end:
a, b = b, a+b
yield b # yield 返回b,同时也会暂停函数的执行,直到下一次next执行,才会继续往下运行
n += 1
s=fibona(10)
print('第1次:', next(s))
print('第2次:', next(s))
print('第3次:', next(s))
print('第4次:', next(s))
8.装饰器
本质还是一个函数,由函数的回调及闭包组成,
不需要改变其他函数的内部结构就可以为函数增加一个额外的功能,
装饰器的返回值也是一个函数对象(函数体)
# 未加工的函数
'''
def v(func):
def f(*args, **kwargs):
print(args, kwargs)
values = func(*args, **kwargs)
return values
return f
def f1(end): # 语法糖后面为装饰函数
return end
f1 = v(f1)
f1(666)
'''
# 使用装饰器加工后
def v(func):
def f(*args, **kwargs):
print(args, kwargs)
values = func(*args, **kwargs)
return values
return f
@v # 语法糖--添加功能 使用,功能函数写在语法糖的上面,
def f1(end): # 语法糖后面为装饰函数
return end
f1=v(f1(666))
print(f1)
9.内置装饰器
@property 调用方法就像调用属性一样
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@property # 调用方法就像调用属性一样,调用a.play() 不用加()
def play(self):
return f'{self.name}正在玩游戏'
a=Person('圣美', 18)
print(a.play) # 调用a.play() 不用加()
@classmethod 第一个参数自动传入类
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod # 第一个参数自动传入类
def play(obj): # obj=Person
return (f'{a.name}正在玩游戏')
a=Person('圣美', 18)
print(a.play())
@staticmethod 不需要传入self,使方法属于这个类
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@staticmethod # 不需要传入self,方法不在属于个人,而是全人类
def play(): # obj=Person
return (f'{a.name}正在玩游戏')
a=Person('圣美', 18)
print(a.play())
十九.继承
通过继承可以很好的提高代码的复用性
1.单继承
class Person: # 人类
def __init__(self, name, age, sex): # __init__ 是初始化函数,在实例化时会自动的调用,帮我们解决属性冲突的问题
# 加入属性,假如属性一开始已经定义好了,那么它将重新赋值为新的属性值
self.name = name # bd.name = '圣美' 属性的添加
self.age = age # bd.age = 18
self.sex = sex # bd.sex = sex
# 实例化后记得为所有的方法加上self,加在参数的第一位,告诫我们方法是属于某个人独有的
def xue(self, name): # 方法 self指的是实例化对象本身 self=a
print(f'{name}在学习')
def gn(self, name):
print(f'姑娘在{name}')
class Person_1(Person):
def xue(self):
print(f'{self.name}不在学习')
class Person_2(Person):
def xue(self):
print(f'姑娘没有看{self.name}')
class Person_3(Person): # 子类继承父类去引用
def xue(self):
Person.xue(self) # 父类直接调用自己的方法
super().xue() # 重写子类,让子类继承父类的方法
print(f'姑娘在看{self.name}')
pass
a = Person_3('圣美', 18, '男')
v = Person_3.mro() # 查看类的继承顺序
print(v)
通过在类后面的跟上要继承的来确定父类
2.多继承
class Person: # 人类
def __init__(self, name, age, sex): # __init__ 是初始化函数,在实例化时会自动的调用,帮我们解决属性冲突的问题
# 加入属性,假如属性一开始已经定义好了,那么它将重新赋值为新的属性值
self.name = name # bd.name = '圣美' 属性的添加
self.age = age # bd.age = 18
self.sex = sex # bd.sex = sex
# 实例化后记得为所有的方法加上self,加在参数的第一位,告诫我们方法是属于某个人独有的
def xue(self): # 方法 self指的是实例化对象本身 self=a
print(f'{self.name}在学习')
def gn(self):
print(f'姑娘在{self.name}')
class Person_1(Person):
def xue(self):
print(f'{self.name}不在学习')
class Person_2(Person):
def xue(self):
print(f'姑娘没有看{self.name}')
class Person_3(Person): # 子类继承父类去引用
def xue(self):
# Person.xue(self) # 父类直接调用自己的方法
# super().xue() # 重写子类,让子类继承父类的方法
print(f'姑娘在看{self.name}')
class Person_4(Person_1,Person_2): # 多继承
def xue(self):
# Person.xue(self) # 直接调用
# Person.gn(self)
# Person_1.xue(self)
# Person_2.xue(self)
# Person_3.xue(self)
print(f'姑娘看到{self.name}在学习')
a = Person_4('圣美', 18, '男')
a.xue()
v = Person_4.mro() # 查看类的继承顺序
print(v)
二十.异常
python中的错误类
1.异常处理
try:…except:
try: # 测试代码中的错误
print(圣美) # 没加引号报错,
except: # 因为try块报错,所以执行该操作
print('unexpected EOF while parsing')
try:…except:…else:
try: # 测试代码中的错误
print('圣美')
except: # 若try块报错,执行该操作
print('unexpected EOF while parsing')
else: # try没问题就执行,有问题就不执行
print('一切正常')
try:…except:…else:…finally:
a = 1
def func():
try: # 检测代码是否异常
print(a)
except Exception as e: # 返回代码异常信息,传给e接收
print('报错了,异常为:', e)
return e # try有问题时返回
else: # try没问题就执行,有问题就不执行
print('继续')
finally: # 以上步骤走完就会去执行
print('最终都会去执行')
return '代码正常时返回的值'
a = func()
raise 抛出错误
if '5<2':
print('5<2')
raise Exception # 直接抛出错误,终止程序
注意事项:
1.try 后面必须跟上 except
2.except 只有在函数中才能使用 return
3.else: try没问题就执行,有问题就不执行
4.finally 不管是否发生异常,始终都会执行
5.raise 可以主动抛出异常
2.assert 断言
a = '圣美'
print(a)
assert a # 断言, 判断是否为真,不为真则报错
为真,则运行
二十一.正则
正则表达式由需要匹配的字符串和一些特殊字符组成,可以在字符串当中匹配出需要查找的对象
通过正则表达式快速快捷的匹配出符合要求的特征字符串
需要导入re模块
import re
1.元字符
2.search()从任意位置匹配
(1)简介
span() 输出索引位置
group() 输出具体匹配到的字符
通配符:
通配符匹配除了换行符之外的任意字符
import re # 正则模块
string = '姑娘喜欢圣美'
s1 = re.search('圣美', string) # 从任意位置开始搜索符合表达式的内容(只有一个符合表达式的 内容)
print(s1) # search返回的是一个正则对象
print(s1.span()) # 输出索引位置
print(s1.group()) #输出具体匹配到的字符
(2)集合[ ]
import re # 正则模块
# 匹配多种可能 [],可以放元字符
string = 'dog ryns to cat'
s1 = re.search(r'r[auzy12345]n', string)
s2 = re.search(r'[a-z0-9]yn', string)
s3 = re.search(r'[^a-zA-Z]', string) # ^ 不匹配这些字符
print(s1.group())
print(s2.group())
print(s3.group())
(3)特殊种类匹配
正则中的反斜杠有其他的意义,因此要去掉字符串本身的转义
\d 匹配所有数字形式 0-9
import re # 正则模块
# \d 匹配所有数字形式 0-9
str1 = 'run r4ns'
s = re.search(r'r\dn', str1)
print(s.group())
# \D :不匹配所有数字形式
str1 = 'run r4ns'
s = re.search(r'r\Dn',str1)
print(s.group())
\s 匹配空白,转义符又称空白符[\t\n\r\f\v]包括空格
import re # 正则模块
# \s 匹配空白,转义符又称空白符[\t\n\r\f\v]包括空格
str1 = 'r n r4ns'
s = re.search(r'r\sn', str1)
a = s.group()
print(a)
print(repr(a)) # 字符串原样输出
# \S 匹配不是空白符的字符
str1 = 'r n rAns'
s = re.search(r'r\Sn', str1)
print(s.group())
\w 匹配所有字母,数字,汉字,下划线
import re # 正则模块
# \w 匹配所有字母,数字,汉字,下划线 [a-zA-Z0-9]
str1 = 'r n r1ns r子n r_n'
s = re.search(r'r\wn',str1)
print(s.group())
s = re.findall(r'r\wn',str1) # 返回以列表的形式
print(s)
# \W 匹配所有不是字母,数字,汉字,下划线
str1 = 'r n r1ns r子n r_n'
s = re.search(r'r\Wn',str1)
print(s.group())
\b 空白字符
import re # 正则模块
# \b:匹配左右两边都是空白符的字符
str1 = 'dog runs\nto cat'
s = re.search(r'\bruns\b',str1)
print(s.group())
# \B:匹配左右两边都不是空白符的字符
str1 = 'dog ArunsA\nto cat'
s = re.search(r'\Bruns\B',str1)
print(s.group())
\u 匹配中文
import re # 正则模块
str1 = " go to 学校"
s = re.search(r'go to [\u4e00-\u9fa5]校',str1)
print(s.group())
\ \ 匹配反斜杆\
import re # 正则模块
str1 = "run\_ to me"
s = re.search(r'run\\_',str1)
print(s.group())
. 匹配除换行符\n 之外的任意字符
import re # 正则模块
str1 = "asdfas\tto me"
s = re.search(r'..s...',str1)
print(s.group())
在匹配点时可以选择加上反斜杆取消点本身能够匹配任意字符的意义 .
脱字符 ^
脱字符匹配开头,必须是以某个字符开头,否则会报错
import re # 正则模块
# 脱字符 ^ shift+6 用于匹配句首,作用在整段字符
str1 = 'dog runs to cat'
s = re.search(r'dog',str1) # 脱字符匹配开头,必须是某个字符开头
print(s.group())
美元符 $
美元符匹配结尾,必须是以某个字符结尾,否则会报错
import re # 正则模块
# 美元符 $ shift+4 用于匹配句尾,作用在整段字符
str1 = 'dog runs to cat'
# s = re.search(r'cat$',str1,flags=re.M) #multi-line 多行匹配,使得每一行都是新的一行
s = re.search(r'to cat$',str1)
print(s.group())
次数匹配 { ,}
import re # 正则模块
str1 = 'abbbb'
s1 = re.search(r'ab{3}',str1) #b匹配3次 ,b小于3个就匹配不了,可以大于3个
s2 = re.search(r'ab{2,10}',str1) #b匹配2次到10次,b小于2个匹配不到,可以大于10个
s3 = re.search(r'ab{1,}',str1) # 一次起
s4 = re.search(r'ab{,2}',str1) # b匹配0到2次
s5 = re.search(r'ab?',str1) # ? 匹配0次或1次 {0,1}
s6 = re.search(r'ab*',str1) # * 匹配0或多次 {0,}
s7 = re.search(r'ab+',str1) # + 至少匹配1次或多次 {1,}
print(s1.group())
print(s2.group())
print(s3.group())
print(s4.group())
print(s5.group())
print(s6.group())
print(s7.group())
分组匹配()
import re # 正则模块
##括号 () 在匹配字符时只会取到括号里面的内容
str1 = 'ID: 021532, Date: Feb/12/2022'
s1 = re.search(r'(\d+), Date: (.+)',str1) # + 是至少匹配1次或多次
print(s1.group())
print(s1.group(1)) # 只输出第一个组里面的内容
print(s1.group(2)) # 只输出第二个组里面的内容
(?P<名字>正则表达式)
import re # 正则模块
##括号 () 在匹配字符时只会取到括号里面的内容
str1 = 'ID: 021532, Date: Feb/12/2022'
##给group组取一个名字
# (?P<名字>正则表达式)
s1 = re.search(r'(?P<id>\d+), Date: (?P<date>.+)',str1)
print(s1.group('id')) # 输出id
print(s1.group('date')) # 输出date
3.findall()找到符合表达式的所有内容
findall()匹配, 匹配所有满足符合条件的字符,与search()方法相似,search中的格式都可以用,返回的是一个列表
import re # 正则模块
##findall 匹配 匹配所有满足符合条件的字符
str1 = 'run ran ren'
s = re.findall(r'r[a-z]n',str1)
print(s)
##| 或者的意思 r[ua]n
str1 = 'rrun ran ren'
s = re.findall(r'(r+|ran)',str1)
print(s)
4.replace()替换
##正则替换 replace re.sub()
str1 = 'dog runs to cat rans dog'
s = str1.replace('dog','pig')
print(s)
s = re.sub(r'r[au]ns','catches',str1)
print(s)
5.split() 切割
import re # 正则模块
##正则切割 re.split() split()
str1 = 'a;b c.d;e'
s = str1.split()
print(s)
s = re.split(r'[,; \.]',str1)
print(s)
6.compile() 提前写好正则格式供我们去使用
import re # 正则模块
##re.compile() 提前写好正则格式供我们去使用
str1 = 'ran to run'
str2 = 'rzn to run'
r = re.compile(r'r[ua]n')
s1 = r.findall(str1)
print(s1)
s2 = r.findall(str2)
print(s2)
7.match() 从头匹配
import re # 正则模块
##re.match() 只匹配一次
str1 = 'ran to run'
s = re.match(r'r[ua]n',str1)
print(s.group())
8.最大最小匹配
import re # 正则模块
html = '<html>this is python</html><tb>PYTHON GOOD</tb>'
# s = re.findall(r'<.*>',html) #贪婪模式 最大匹配
# s = re.findall(r'<.*?>',html) #非贪婪模式 最小匹配
# s = re.findall(r'<(.*?)>',html) #不想加上尖括号就使用group组
s = re.findall(r'<(?:.*?)>',html) #想加上尖括号就使用?:
print(s)