1、Python
1.1 Python介绍
1.1.1 Python语言的介绍
- Python就是—门解释型的编程语言,而且是现在世界上最流行的编程语言之一。
1.1.2 pip
-
pip管理Python包
- 安装指定的包:pip install<包名>
- 删除指定的包:pip uninstall<包名>
- 显示已经安装的包:pip list
- 显示已经安装的包,并且以指定的格式显示:pip freeze
- 安装required.txt文件里列出的安装包:pip install -r required.txt
-
修改pip下载源
pip install 包名 -i 国内源地址
国内源地址:
阿里云 https://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣(douban) https://pypi.douban.com/simple/
清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
中国科学技术大学 https://pypi.mirrors.ustc.edu.cn/simplel
1.1.3 pycharm快捷键
-
快捷键
格式化代码:ctrl + l
注释代码:ctrl + /
-
修改快捷键
File——Setting——Keymap
1.2 变量和数据类型
1.2.1 注释
-
单行注释
#单行注释
-
多行注释
""" 多行注释 """ ''' 多行注释 '''
1.2.2 变量和数据类型
-
变量的定义
变量名 = 变量值
-
数据类型
类型 实例 int n = 1 float n = 1.1 str n = “yang” complex n = complex(1,2) bool n = True list n = [1,2,3] tuple n = (1,2,3) set n = {1,2,3} dict n = {1:2,2:True,“name”:“yang”} -
type()
使用type()查看数据类型
n = 2 m = 20.0 t = "yang" k = True a = [] b = () c = {1,2} d = {1:2,2:"yang"} print(type(n),type(m),type(t),type(k),type(a),type(b),type(c),type(d))
1.2.3 标识符和关键字
-
标识符
变量名、函数名、类名、模块名等都可称为标识符
#变量名 n = 1 #函数名 def ok(): pass #类名 class text(): pass #模块名 import random
-
标识符的命名标准
- 由字母、数字、下划线组成,且不能以数字开头。
- 严格区分大小写
- 不能使用关键字
- 命名尽量不要使用中文
- 顾名思义
- 命名规范:大、小驼峰命名法、 使用下划线连接
-
常见关键字
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PqEaJXsb-1664335392573)(.\Img\0225.png)]
1.2.4 输出语句
-
print()
print("1","2",sep = "_",end = "\n",file = None)
- sep:为分割符,默认为空格
- end:为换行符,默认为\n
- file:指定打印的位置,默认为None
-
格式化输出
id = 1 name = "yang" age = 18 score = 92.5 print("id:%d,name:%s,age:%d,score:%.2f",%(id,name,age,score)) print(f"id:{id},name:{name},age:{age},score:{score}")
-
常用格式符号
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XNwLphAq-1664335392574)(.\Img\0226.png)]
1.2.5 输入语句
-
input()
n = input("请输入信息:")
- input()返回一个字符串
- 括号里可以写提示信息
1.2.6 类型转换
-
常见类型转换
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mVbsEtLp-1664335392575)(.\Img\0230.png)]
-
其他类型转换
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FLXNaPMy-1664335392576)(.\Img\0227.png)]
-
转换为int类型
n = "10" print(int(n)) m = "1a" #base = 16 表示以16进制输出 print(m,base = 16)
-
转换为float类型
n = "10.2" print(float(n))
-
转换为str类型
n = 123 print(str(n))
-
转换为bool类型
#转换值为False的bool类型 a = "" #空字串 b = 0 #数值0 c = None #None d = () #空元组 e = [] #空列表 f = set() #空集合 g = {} #空字典 print(bool(a),bool(b),bool(c),bool(d),bool(e),bool(f),bool(g)) #转换值为True的bool类型 #除以上7种空类型外,其他都可以转换值为True的bool类型
1.3 运算符
1.3.1 算数运算符
-
算数运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vWq4k5Cl-1664335392577)(.\Img\0228.png)]
注意:优先级顺序:** 高于 *、/、// 、% 高于 +、-
-
数字和字符串乘法的运用
#多字符串进行重复复制 n = 3 m = "yang" print(m*n)
-
字符串与字符串加法运算
#将字符串进行连接 n = "I " m = "LOVE " t = "YOU" print(n + m + t)
1.3.2 赋值运算符
-
赋值运算符
运算符 描述 实例 = 赋值运算符 把=号右边的结果赋给左边的变量
如num = 1 + 2 * 3,结果num的值为7+= 加法赋值运算符 c += a等效于c = c + a -= 减法赋值运算符 c -= a等效于c = c - a *= 乘法赋值运算符 *c = a等效于c = c * a /= 除法赋值运算符 c /= a等效于c = c / a //= 整除赋值运算符 c //= a等效于c = c // a %= 取模赋值运算符 c %= a等效于c = c % a **= 幂赋值运算符 c **= a等效于c = c** a -
=
#连着赋值 x = y = z = 20 #元组(可省略括号) n = 2,3,4 #拆包(变量和值的个数要对应) a,b,c = 1,2,3 #长度可变变量赋值 a,*b,c =1,2,3,4,1,9
1.3.3 比较运算符
-
比较运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xZe4zLdJ-1664335392578)(.\Img\0236.png)]
-
数字与字符串进行比较
- 数字 == 字符串,返回False。
- 数字 != 字符串,返回True,使用其他比较运算符将会报错。
-
字符串和字符串做比较运算
- 按照字符的编码值逐一进行比较
-
获取一个字符对应的编码
ord("a")
-
获取编码对应的字符
chr(97)
1.3.4 逻辑运算符
-
逻辑运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QJBkEC8D-1664335392579)(.\Img\0237.png)]
-
取值问题
- 逻辑and运算在取值时,取第一个为False的值,若全部值为True,则取最后一个值。
- 逻辑or运算在取值时,取第一个为True的值,若全部值为False,则取最后一个值。
1.3.5 位运算符
-
位运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oBKO5yk4-1664335392580)(.\Img\0238.png)]
-
运算规则
- 按位与运算:将数字转为二进制再计算,同为1结果为1,否则为0
- 按位或运算:将数字转为二进制再计算,只要有1则为1,否则为0
- 按位异运算:将数字转为二进制再计算,同为1则为1,同为0则为1,否则为0
- 按位取反运算:将数字转为二进制再计算,1变0,0变1
- 左移运算:x << n <==> x * 2 ** n
- 右移运算:x >> n <==> x / 2 ** n
-
二进制、八进制、十进制、十六进制
# 二进制 n = 0b0001 # 二进制以0b开头 bin(12) # 将其他进制数字转为二进制 #八进制 n = 0o34 # 八进制以0o开头 oct(12) # 将其他进制数字转为八进制 #十进制 n = 20 #十六进制 n = 0xf0384e # 十六进制以0x开头 hex(12) # 将其他进制数字转为十六进制
-
例题分析1
使用位运算,获取到十六进制颜色
0xF0384E
的RGB值,以十进制形式打印输出。color = 0xF0384E # 1111 0000 0011 1000 0100 1110 red = color >> 16 # 1111 0000 green = color >> 8 & 0xFF # 1111 0000 0011 1000 & # 0000 0000 1111 1111 = # 0000 0000 0011 1000 bule = color & 0xFF # 1111 0000 0011 1000 0100 1110 & # 0000 0000 0000 0000 1111 1111 = # 0000 0000 0000 0000 0100 1110 print(color,green,bule)
1.3.6 运算符的优先级
-
优先级(高——>低)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-el4I7Zl1-1664335392580)(.\Img\0239.png)]
1.4 流程控制语句
1.4.1 条件判断语句
-
语法
if 判断条件: pass elif 判断条件: pass . . . else: pass
-
三元表达式
n = n1 if n1 > n2 else n2
注:三元表达式可以嵌套,但不可使用elif
-
例题分析1
猜拳游戏
import random while 1: n = int(input("请输入剪刀(0)、石头(1)、布(2):")) if n != 0 and n != 1 and n != 2: print("你特喵出了个啥,请重新输入!!!") continue t = random.randint(0, 2) if n == t: print("平局") elif (n == 0 and t == 2) or (n == 1 and t == 0) or (n == 2 and t == 1): print("你牛皮") else: print("小垃圾")
-
指定生成范围随机整数
import random # 随机生成10~20之间的整数 random.randint(10,20)
1.4.2 循环语句
-
while语句
-
语法
while 判断条件: pass else: pass
-
-
break、continue
- break是中断此循环语句。
- continue是跳过本次循环,进入下一次循环。
- break和continue只能出现在循环语句中(while、for)
-
例题分析1(嵌套循环)
求100以内的质数
i = 100 while i > 1: j = 2 while j <= i ** 0.5: if i % j == 0: break j = j + 1 else: print(f"{i}是质数") i = i - 1
-
例题分析2(嵌套循环)
打印九九乘法表
i = 1 while i <= 9: j = 1 while j <= i: print(f"{j}x{i}={i * j} ", end="") j = j + 1 i = i + 1 print("\n")
-
例题分析2(嵌套循环)
冒泡排序
list = [22, 50, 90, 1, 50, 70] print(f"排序前的序列:{list}") for i in range(len(list)): for j in range(len(list) - i - 1): if list[j] > list[j + 1]: list[j], list[j + 1] = list[j + 1], list[j] print(f"排序后的序列:{list}")
-
for语句
-
语法
for 循环变量 in 可迭代对象: 语句 else: 语句 # 可迭代对象:字符串、列表、元组、字典、集合
-
-
range()
range(n,m,k)是生成以步长k从n~m的数字
- n代表开始的的数字
- m代表结束的数字(生成的数字不包含m)
- k代表步长
-
例题分析3
求100以内的质数
for i in range(2, 101): for j in range(2, i): if i % j == 0: break else: print(f'{i}是质数')
1.5 字符串、列表、元组、字典、集合
1.5.1 字符串
-
常用转义字符
\' # 单引号 \" # 双引号 \\ # 反斜杠 \n # 换行 \r # 回车 \t # 制表符
-
r"字符串"
字符串前加入r,则表示字符串原样输出
-
字符串输入、输出
# 字符串输入 n = input() # 字符串输出 print("%s" % n)
-
字符串下标
n = "abcdef" n[i] # 表示字符串的第i个字符
-
字符串切片
n = "abcdefghijklmn" n[i:j] # 表示获取字符串的[i,j)子字符串 n[i:j:k] # 表示以步长为k获取字符串的[i,j)子字符串 n[i:] # 表示获取字符串从第i个字符开始到最后一个字符的子字符串 n[:j] # 表示获取字符串的[0,j)子字符串 n[-i:-j] # 表示获取字符串的从倒数第i个到倒数第j个的字符 n[i:j:-k] # 表示从后向前以步长k获取字符串
-
字符串常用方法
n = "abcdefghigk" # 获取字符串长度 len(n) # 查找指定字符串是否存在字符串中,若找到返回下标,找不到则返回-1 n.find("bc") n.find("bc",3) # 从下标3开始查找字符串是否存在指定字符串中 n.find("bc",3,5) # 从下标3开始到下标5结束查找字符串是否存在指定字符串中 n.rfind("bc") # 从右向前开始查找指定字符串是否存在字符串中 # 查找指定字符串是否存在字符串中,若找到返回下标,找不到报异常错误 n.index("bc") n.rindex("bc") # 从右向前开始查找指定字符串是否存在字符串中 # 判断字符串是否以指定字符串开头,返回值为bool类型 n.startswith("bc") # 判断字符串是否以指定字符串结尾,返回值为bool类型 n.endswith("bc") # 判断字符串是否是纯字母组成,返回值为bool类型 n.isalpha() # 判断字符串是否是纯数字组成,返回值为bool类型 n.isdigit() # 判断字符串是否是数字或字母组成,返回值为bool类型 n.isalnum() # 判断字符串是否是纯空格组成,返回值为bool类型 n.isspace() # 统计指定字符串在字符串中出现的次数 n.count("bc") # 以指定字符串替换字符串中的子字符串 n.replace("bc","cd") n.replace("bc","cd",2) # 指定替换次数最多为2次 # 以指定字符串分割字符串,返回值为list类型 n.split("bc") n.split("bc",2) # 最多以指定字符串分割2次 n.rsplit("bc",2) # 从右向左进行分割,最多分割2次 n.splitlines() # 以行(\n)对字符串进行分割 # 以指定字符串分割字符串为三部分(指定字符串前,指定字符串,指定字符串后),返回值为元组 n.partition("bc") n.rpartition("bc") # 从右向左以指定字符串分割字符串为三部分 # 对字符串首字母转换为大写 n.capitalize() # 对字符串中的每个单词首字母转换为大写 n.title() # 对字符串中的所有小写字母转换为大写 n.upper() # 对字符串中的所有大写字母转换为小写 n.lower() # 返回指定长度的字符串 n.ljust(30) # 若指定长度小于原字符串长度,返回原字符串 # 若指定长度大于原字符串长度,返回对原字符串左边进行空格补全 n.rjust(30) # 若指定长度小于原字符串长度,返回原字符串 # 若指定长度大于原字符串长度,返回对原字符串右边进行空格补全 n.center(30) # 若指定长度小于原字符串长度,返回原字符串 # 若指定长度大于原字符串长度,返回对原字符串两边进行空格补全 # 删除空白字符串 n.lstrip() # 删除字符串左边的空格 n.rstrip() # 删除字符串右边的空格 n.strip() # 删除字符串两边的空格 # 字符串的拼接 n.join("123") # 返回原字符串的每个字符与指定字符串的拼接 n.join(["1","2"]) # 返回列表的每个元素和指定字符串的拼接 n.join(("1","2")) # 返回元组的每个元素和指定字符串的拼接
-
字符串的format方法
name = "yang" sex = "男" age = 18 # 使用{}占位 print("姓名:{},性别:{},年龄:{}".format(name,sex,age)) # 使用{下标}占位 print("姓名:{1},性别:{0},年龄:{2}".format(sex,name,age)) # 使用{变量}占位 print("姓名:{b},性别:{a},年龄:{c}".format(a=sex,b=name,c=age)) # 使用{}和{变量}混合占位 print("姓名:{},性别:{a},年龄:{}".format(name,a=sex,age)) # 使用{下标}和{变量}混合占位 print("姓名:{1},性别:{0,年龄:{a}".format(sex,name,a=age)) # 对列表中元素使用{}占位 names = ["a","b","c","d"] print("同学们:{},{},{},{}".format(*names)) # 对字典中元素使用{key}占位 student_info = ["name":"yang","sex":"男","age":18] print("姓名:{name},性别:{sex},年龄:{age}".format(**student_info)) # 转换字段 print("{name!a}".format(name="yang")) #返回指定字符串的ASCII码 # format对其他形式的操作 print('编号:{:_>3}'.format("a")) # 输出 编号:__a print('编号:{:_<3}'.format(2)) # 输出 编号:2__ print(f'编号:{9:#>3}') # 输出 编号:##9
-
字符串编码
# 将字符串转为ASCII码 ord("a") # 将ASCII码转为对应的字符串 chr(97) # 将字符串编码位二进制 "yang".encode(encoding="utf8") # 将二进制解码位字符串 b"\xe4".decode(encodeing="utf8")
1.5.2 列表
-
列表
列表是可变数据类型,支持增删改查
-
空列表
li = []
-
可迭代对象转为列表
list(可迭代对象)
-
下标
li = [1,2,3,4,5] # 使用下标获取列表中的元素 li[0] # 返回1 li[4] # 返回5
-
切片
li = ["yang",1,"123",True] # 使用切片获取子列表 li[0:2] # 返回["yang",1,"123"]
-
列表的增删改查
li = ["yang",1,"123",True] # 列表的增 li.append("321") # 在列表的最后插入指定元素 li.insert(1,"456") # 在列表的指定下标位置插入指定元素 li.extend(["741","852"]) # 将列表和指定列表进行合并 # 列表的删 li.pop(1) # 根据下标删除元素,返回值为删除的元素 li.remove("123") # 删除列表中的指定元素,若列表中无指定元素则报错 del li[1] # 根据下标删除元素 # 列表的改 li[1] = 2 # 使用下标来修改列表中的元素 # 列表的查 li.index("123") # 返回查找元素的下标,若列表中无查找元素则报错 li.index("123",1,3) # 在指定范围内查找元素,返回查找元素的下标 # 若列表中无查找元素则报错
-
列表元素的统计
li = ["yang",1,"123",True] # 统计指定元素在列表中出现的次数 li.count("123")
-
列表的排序
li = ["a","b","c","d"] # 对列表升序排序 li.sort() # 对列表降序排序 li.sort(reverse=True) # 对列表逆置(不排序) li.reverse()
-
列表的遍历
li = ["a","b","c","d"] # 操作下标 for i in range(len(li)): print(li[i]) # 直接遍历列表 for x in li: print(x) # 使用enumerate内置类实现带下标的遍历 for x in enumerate(li): print(x[0],x[1]) for x,v in enumerate(li): print(x,v)
1.5.3 元组
-
元组
元组是不可变数据类型,只支持查,不支持增删改
-
空元组
di = ()
-
元组的查
tu = ("1","2","3","a","b","c") # 元组的查 tu[0] # 返回下标对应的值 tu.index("3") # 查找元组中指定元素的下标,若元组中无指定元素则报错 # 统计元组中指定元素的个数 tu.count("a") # 若元组中只有一个元素,需要在元素后加逗号 tu = ("abc",)
1.5.4 字典
-
字典
- 字典是可变的数据类型,支持增删改查
- 数据以键值对的形式存在,key唯一,且key必须是不可变的数据类型
-
空字典
di = {}
-
字典的增删改查
di = {"name":"yang",1:"123",2:"yang"} # 字典的增 di["age"] = 18 # 若key值存在,则会修改key对用的values # 若key值不存在,则增加新元素 di.setdefault("height":170) # 若key值存在,则不修改字典 # 若key值不存在,则增加新元素 di.update({"weight":50}) # 若key值存在,则会修改key对用的values # 若key值不存在,则增加新元素 # 字典的删 di.pop("name") # 根据key值删除元素 di.popitem() # 删除字段的最后一个元素 del di # 删除整个字典 clear di # 清空字典的所有元素 # 字典的改 di["name"] = "ssun" # 若key值存在,则会修改key对用的values # 若key值不存在,则增加新元素 # 字典的查 di["name"] # 通过key值获取对应的values # 若key值不存在,则报错 di.get("name") # 通过key值获取对应的values # 若key值不存在,则返回None di.get("name","ssun") # 通过key值获取对应的values # 若key值不存在,则返回默认值 ssun
-
字典的遍历
di = {"name":"yang",1:"123",2:"yang"} # 通过key值获取values for k in di: print(di[k]) for k in di.key(): print(di[k]) # 直接遍历values for v in di.values(): print(v) # key值和values一起使用 for k,v in di.items(): print(k,v)
1.5.5 集合
-
集合
集合是无序且元素不可重复的数据类型
-
空集合
st = set()
-
集合的增删
st = {'zhangsan', 'lisi', 'jack', 'tom'} # 集合的增 st.add("yang") st.update(["ssun","lang"]) # 将集合与列表合并,并去重 st.update(("ssun",)) # 将集合与元组合并,并去重 st.update(("name":"ssun","age":18)) # 将集合与字典的key值合并,并去重 # 集合的删 st.pop() # 随机删除一个元素 st.remove("yang") # 删除元组中的指定元素,若删除的元素不存在,则报错
-
集合的遍历
st = {'zhangsan', 'lisi', 'jack', 'tom'} # 随机遍历 for x in st: print(x) for i,x in enumerate(st): print(i,x)
1.5.6 公共方法
-
公共方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aByQia1E-1664335392583)(.\Img\0247.png)]
注:在对字典使用not或not in时,是判断的key值
1.5.7 列表推导式
-
列表推导式
列表推导式就是使用轻量级循环创建列表
-
列表推导式的使用
# 列表推导式中嵌套if # 获取1~100的偶数 nums = [i for i in range(1, 101) if i % 2 == 0] # 列表推导式中嵌套for # 返回(x,y)的数据 points = [(x, y) for x in range(0, 5) for y in range(5, 10)] # 字典中的使用 # 将字典的key和value互换 di_1 = {"a": 100, "b": 200, "c": 300} di_2 = {v: k for k, v in dict1.items()}
1.6 函数
1.6.1 函数基础
-
函数的定义
# 语法 def 函数名([参数...]): pass
-
函数的调用
# 调用 函数名([参数...]) # 可指定形参的数据类型 def test(a:int): pass
-
函数的返回值
执行return语句,将结束函数执行
# 使用return可返回指定数据类型的数据 def test(): x = 10 y = 20 return x,y # 返回一个元组 # return [x,y] # 返回一个列表 # return {"x":x,"y":y} # 返回一个字典 # return {x,y} # 返回一个集合
-
函数的参数
定义形参的顺序:位置参数、可变的位置参数、缺省参数、可变关键字参数
# 位置参数:是对照位置进行传参 def test(name,age): pass test("yang",18) # 可变的位置参数:以元组的形式接受多个参数 def test(*args): pass test("yang",18,170) # 缺省参数:传参时需要指定形参变量,若不对其进行传参,则使用默认值 def test(name="yang"): pass test() # 不对其传参,则使用默认值 test(name="ssun") # 对其传参,使用传入的值 # 可变关键字参数:传参时需要需要指定形参变量,多个关键字参数 def test(**kwargs): pass test(name="yang",age=18,sex="男") # 位置参数、可变的位置参数、缺省参数、可变关键字参数 def test(name,*args,age=18,**kwargs): pass
1.6.2 函数高级
-
变量的作用域
-
全局变量
作用域时当前文件
-
局部变量
作用域只在当前所定义的函数内部
-
若想在函数内部使用并改变全局变量
n = 10 # 全局变量 def test(): global n # 使用global关键字,表示在函数内部可以使用并改变此全局变量
-
查看所有的全局变量和局部变量
# 查看全局变量 globals() # 查看局部变量 locals()
-
-
可变/不可变数据类型
-
可变数据类型:列表、字典、集合
若对其进行修改,则内存地址不会发生改变
-
不可变数据类型:数字、字符串、元组
若对其进行修改,则内存地址会发生改变
-
获取变量的内存地址
id()
-
使用可变/不可变数据类型传参
使用可变数据类型:修改形参,不影响实参
使用不可变数据类型:修改形参,影响实参
-
-
copy的使用
# 列表中的copy li = [1,2,3,4] x = li.copy() # li与x共享列表 # 模块copy import copy di = {"name":"yang","age":18} x = copy.copy(di) # 浅拷贝,复制字典的数据,并另开辟空间将其存储 # 即x与li所指向的字典不是同一个 li = [1,2,3,4,[5,6]] x = copy.copy(li) # 浅拷贝,复制列表的数据,并另开辟空间将其存储 # 但是对于列表中的元素是列表的情况,不能将其复制 # 即x与li所指向的列表不是同一个 # 但是列表中是列表的元素仍旧被x与li共享 li = [1,2,3,4,[5,6]] x = copy.deepcopy(li) # 深拷贝,复制列表的数据,并另开辟空间将其存储 # 即x与li所指向的列表不是同一个
1.6.3 递归函数
-
例题分析1
求斐波那契数列的第n个值
# 不使用递归函数实现 def fibonacci_sequence(n): num_1 = num_2 = 1 for i in range(n - 1): num_2,num_1 = num_1 + num_2,num_2 return num_1 print(fibonacci_sequence(10)) # 使用递归函数实现 def fibonacci_sequence(n): if n == 1 or n == 2: return 1 return fibonacci_sequence(n - 2 ) + fibonacci_sequence(n - 1) print(fibonacci_sequence(10))
1.6.4 匿名函数
-
匿名函数的介绍
-
语法
lambda 参数列表:运算表达式
-
函数别名
# 定义一个函数 def test(): pass # 将函数的返回值赋予变量 x = test() # 将函数赋值给变量(相当于给函数起了个别名) y = test print(y()) # 使用此变量可对函数进行操作
-
匿名函数作为参数
当把一个函数A当做另一个函数B的参数使用时,可以将函数A定义成为匿名函数
def B(x,y,fn): n = fn(x,y) return n print(B(10,20,lambda x,y:x*y))
-
匿名函数使用场景
persons = [ {'name': 'jack', 'age': 18, 'height': 178}, {'name': 'tony', 'age': 20, 'height': 180}, {'name': 'zhangsan', 'age': 19, 'height': 177}, {'name': 'lisi', 'age': 17, 'height': 179} ] # 把 persons 列表按照年龄降序排序 persons.sort(key=lambda ele: ele['age'],reverse=True) print(persons)
-
1.6.5 常见内置函数
-
输入输出函数
# 输出 print() # 输出 input()
-
数序相关函数
# 绝对值 abs() # 取得整除商和余数 divmod(除数,被除数) # 得到一个元组(商,余数) # 幂运算 pow(x,n) # 对浮点数四舍五入 round(浮点数值,小数点保留的位数)
-
可迭代对象相关函数
# 查看可迭代对象里所有的元素转换成为布尔值是否全是True all(可迭代对象) # 查看可迭代对象里的元素转换成为布尔值,是否有一个是True any(可迭代对象) # 获取到可迭代对象的迭代器 iter() # 获取到迭代器的下一个数据 next() # 用来获取可迭代对象的长度 len(可迭代对象) # 获取可迭代对象的最大/最小值 max(可迭代对象) min(可迭代对象) # 用来排序,不改变原有的数据,生成一个新的结果 sorted() # 例如 tu = (9, 4, 2, 1, 6, 7, 8, 2, 3, 4, 6) x = sorted(tu) print(x) # 求和 sum()
-
判断相关函数
-
callable()
# 判断一个变量是否可以被调用(判断这个变量是否是函数的别名) def test(): pass a = test print(callable(a)) # True
-
isinstance()
# 用来判断一个对象是否是由指定的类(或指定类的父类)创建的 class A: pass class B: pass class C(A,B): pass p = C() print(isinstance(p,C)) # True print(isinstance(p,B)) # True print(isinstance(p,A)) # True print(isinstance(p,(A,B))) # True
-
issubclass()
# 用来判断一个类是否是另一个类的子类 class A: pass class B: pass class C(A,B): pass print(issubclass(C,A)) # True print(issubclass(C,B)) # True print(issubclass(C,(A,B))) # True
-
-
对象属性相关函数
-
delattr()
# 用来删除一个对象属性 class Person: def __init__(self, name, age): self.name = name self.age = age p = Person("yang",18) # 创建实例对象 delattr(p,"name") # 删除实例对象p的name属性 print(p.name) # 报错,因为已经删除了其name属性
-
getattr()
# 用来获取一个对象的属性 class Person: def __init__(self, name, age): self.name = name self.age = age p = Person("yang",18) # 创建实例对象 print(getattr(p, "name")) # 获得实例对象p的name属性的值,<==> p.name
-
setattr()
# 用来设置一个对象的属性 class Person: def __init__(self, name, age): self.name = name self.age = age p = Person("yang",18) # 创建实例对象 setattr(p,"name","ssun") # 修改实例对象p的name属性的值 # <==> p.name = "ssun" print(p.name) # 输出 ssun
-
dir()
# 用来列出一个对象所有的属性和方法 class Person: def __init__(self, name, age): self.name = name self.age = age p = Person("yang",18) # 创建实例对象 print(dir(p)) # 输出实例对象的属性和方法列表
-
vars()
# 如果不传递参数,等价于locals;如果传递参数,用来将对象转换成为字典 class Person: def __init__(self, name, age): self.name = name self.age = age p = Person("yang",18) # 创建实例对象 print(vars()) # 输出所在作用域的方法,<==> locals() print(vars(p)) # 将实例对象p中的属性和值转为对应的字典 # <==> p.__dict__
-
-
作用域相关函数
# 查看全局变量 globals() # 查看当前作用域局部变量 locals()
-
获取对象的内存地址的函数
id()
-
查看帮助文档函数
help()
-
打开一个文件,获取到文件流
open()
-
用来结束整个程序函数
exit() quit()
-
转换相关函数
# 查看Unicode编码 ascii() # 将数字转换成为二进制/八进制/十六进制 bin() oct() hex() # 将字符转换成为对应的编码 ord() # 获取编码对应的字符 chr() # 将一个字符串转换成为python代码并执行 eval() # 将一个对象转换成为字符串 repr()
1.6.6 列表的常用操作
-
列表的常用操作(reduce()、filter()、map())
persons = [ {'name': 'jack', 'age': 18, 'height': 178}, {'name': 'tony', 'age': 20, 'height': 180}, {'name': 'zhangsan', 'age': 19, 'height': 177}, {'name': 'lisi', 'age': 17, 'height': 179} ] from functools import reduce # 计算列表中用户的年龄和 age = reduce(lambda x, y: x + y['age'], persons, 0) # 获取身高大于178的用户信息 f = filter(lambda ele: ele['height'] > 178, persons) print(list(f)) # 对列表中所有用户的年龄减一 m = map(lambda ele: ele['age'] - 1, persons) print(list(m))
1.6.7 闭包
-
什么是闭包
一个内部函数对外部作用域的局部变量的引用,则认为此内部函数是闭包
-
例题分析1
def demo(): n = 10 # 对demo()函数中定义的变量 # 定一个内部函数 def inner(): nonlocal n # 表示inner()对此外部变量拥有改变的权限 n = 20 inner() # 调用内部函数
1.6.8 装饰器
-
计算一段代码运行的时间
import time # 定义一个计算1~1000的和的函数 def factorial(): sum = 0 for i in range(1,10001): sum = sum + i return sum # 定义一个计算一段代码运行时间的函数 def run_time(fn): start_time = time.time() sum = fn() end_time = time.time() return sum,end_time - start_time # 调用run_time()函数 print(run_time(factorial))
-
使用装饰器计算一段代码运行时间
def run_time(fn): def inner(): start_time = time.time() sum = fn() end_time = time.time() return sum,end_time - start_time return inner # 定义一个计算1~1000的和的函数 @run_time def factorial(): sum = 0 for i in range(1,10001): sum = sum + i return sum # 调用factorial()函数其实调用的是inner()函数 print(factorial())
-
被装饰的函数带参数
编写一个玩游戏超过时长将不能玩了,未达时长可继续玩耍
def can_play(fn): def action(name,game,*args,**kwargs): if not args: clock = kwargs.get("clock",5) else: clock = args[0] if clock >= 5: print("不能玩了!") else: fn(name,game) return action @can_play def play_game(name,game): print(f"{name}正在玩儿{game}") play_game("yang","王者荣耀",4) play_game("ssun","王者荣耀",clock=5) play_game("yang","绝地求生",3,clock=3,a="hhh",b="jjjj")
-
使用装饰器验证权限
验收用户有几个权限
# 定义权限因子 READ_PERMISSION = 1 WRITE_PERMISSION = 2 EXECUTE_PERMISSION = 4 DELETE_PERMISSION = 8 UPDATE_PERMISSION = 16 # 用户权限 user_permission = 5 # 定义函数来判断用户所拥有的的权限 def check_permission(base_permission): def handle_action(fn): def do_action(): if user_permission & base_permission: fn() return do_action return handle_action # 读取权限 @check_permission(READ_PERMISSION) def read(): print('读取权限') # 写入权限 @check_permission(WRITE_PERMISSION) def write(): print('写入权限') # 执行权限 @check_permission(EXECUTE_PERMISSION) def execute(): print('执行权限') # 删除权限 @check_permission(DELETE_PERMISSION) def delete(): print('删除权限') # 更新权限 @check_permission(UPDATE_PERMISSION) def update(): print('更新权限') # 查看用户的权限 def user_all_permission(): read() write() execute() delete() update() # 调用user_all_permission()函数 user_all_permission()
1.6.9 函数的综合练习
-
名片管理系统
# 名片管理系统 # 添加名片 # 用于存储用户名片 persons = [] # 用户编号 user_id = -1 # 添加名片 def insert_user(): while 1: name = input("请输入您的姓名:") for x in persons: if x["name"] == name: print("您输入的用户名已存在,请重新输入!") break else: break tel = input("请输入您的手机号:") qq = input("请输入您的QQ:") global user_id user_id = user_id + 1 di = {"id": user_id, "name": name, "tel": tel, "qq": qq} persons.append(di) return # 删除名片 def delete_user(): while 1: name = input("请输入您要删除的名片的名字:") for x in persons: if x["name"] == name: while 1: n = input("您确定要删除吗?(yes/no):") if n.lower() == "yes": persons.remove(x) print("-" * 26 + "您已经成功删除了名片!" + "-" * 26) return elif n.lower() == "no": print("-" * 26 + "您已经退出删除名片页面!" + "-" * 26) return else: print("您输入的有误,请重新输入!") else: print("您输入的用户名字不存在,请重新输入!") # 修改名片 def update_user(): while 1: name = input("请输入您要修改的名片的名字:") for x in persons: if x["name"] == name: print(f"您要修改的信息是:\ 姓名:{x['name']},电话:{x['tel']},QQ:{x['qq']}") new_name = name while 1: new_name = input("请输入您的新名字:") for y in persons: if y["name"] == new_name and name != new_name: print("您输入的名字已经存在,请重新输入!") break else: break tel = input("请输入您的手机号:") qq = input("请输入您的QQ:") # 可再一次确认操作 x["name"] = new_name x["tel"] = tel x["qq"] = qq print("-" * 26 + "您已经成功修改了名片!" + "-" * 26) return else: print("您输入的用户名字不存在,请重新输入!") # 查询名片 def select_user(): name = input("请输入您要查询的名片的姓名:") for x in persons: if x["name"] == name: print(f"查询的名片信息:姓名:{x['name']},电话:{x['tel']},QQ:{x['qq']}") return else: print("您要查询的名片不存在...") # 显示所有名片 def show_all_user(): print("序号".ljust(5), "姓名".ljust(15), "电话".ljust(15), "QQ".ljust(15)) for x in persons: print(str(x["id"]).ljust(6), x["name"].ljust(17), x["tel"].ljust(16), x["qq"].ljust(17)) # 退出系统 def exit_system(): while 1: n = input("您确定要退出?(yes/no):") if n.lower() == "yes": print("-" * 26 + "您已经退出系统,欢迎下次光临!" + "-" * 26) exit() elif n.lower() == "no": print("-" * 26 + "您已经退出了退出系统页面!" + "-" * 26) return else: print("您输入的指令有误,请重新输入!") # 提示信息 print( "-" * 26 + "名片管理系统 v1.0" + "-" * 26 + "\n 1:添加名片 \n 2:删除名片 \n 3:修改名片 \n 4:查询名片 \n 5:显示所有名片 \n 6:退出系统 \n" + "-" * 67) # 判断进入的接口 while 1: # 输入操作指令(1~6) operating = int(input("请输入你的操作指令(0~6):")) if operating == 1: # 添加名片 print("-" * 26 + "您进入的是添加名片页面!" + "-" * 26) insert_user() print("-" * 26 + "您已经成功添加了名片!" + "-" * 26) elif operating == 2: # 删除名片 print("-" * 26 + "您进入的是删除名片页面!" + "-" * 26) delete_user() elif operating == 3: print("-" * 26 + "您进入的是修改名片页面!" + "-" * 26) # 修改名片 update_user() elif operating == 4: # 查询名片 print("-" * 26 + "您进入的是查询名片页面!" + "-" * 26) select_user() print("-" * 26 + "您已经退出了查询名片页面!" + "-" * 26) elif operating == 5: # 显示所有名片 print("-" * 26 + "您进入的是显示名片页面!" + "-" * 26) show_all_user() print("-" * 26 + "您已经退出了显示名片页面!" + "-" * 26) elif operating == 6: # 退出系统 print("-" * 26 + "您进入的是退出系统页面!" + "-" * 26) exit_system() else: # 错误指令 print("你特喵输入了个啥!")
1.7 文件操作
1.7.1 路径
-
绝对路径
D:/03.自学资料/阿里云大学/text.py
-
相对路径
…/test.py
1.7.2 文件的操作
-
文件的打开与关闭
-
文件的打开
open(文件路径,访问模式)
file = open("text.txt".mode="r")
访问模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EqVZdErA-1664335392584)(.\Img\0248.png)]
-
文件的关闭
file.close()
-
-
文件的编码方式
open("test.txt",mode="r",encoding="utf8") # encoding用来指定解码方式,默认用操作系统的编码方式
-
文件的读写操作
-
文件的读取
# 打开文件 file = open("test.txt",mode="r",encoding="utf8") file.read() # 读取文件的内容 file.read(1024 * 1024) # 读取文件内容前1M的数据 file.readable() # 判断文件是否可读 file.readline() # 读取文件的第一行 file.readlines() # 读取文件的所有内容
-
文件的写入
# 打开文件 file = open("test.txt",mode="w",encoding="utf8") file.write("你是谁".encode("utf8")) # 以utf8的编码形式写入文件 file.writable() # 判读文件是否可写入 file.writelines(["你","是","谁","?"]) # 将列表中的数据以一行的形式写入文件
-
-
文件的复制
import os file_name = input('请输入您要备份的文件路径:') if os.path.exists(file_name): # 判断文件路径是否存在 names = file_name.rpartition('.') # 将文件名分为三部分 new_name = names[0] + '.bak.' + names[2] # 拼接形成新文件名 new_file = open(new_name, 'wb') # 以二进制写入方式创建并打开新文件 file = open(file_name, 'rb') # 以二进制的读取方式打卡备份文件 while True: # 循环读取文件的内容并写入新文件 content = file.read(1024 * 1024) # 每次读取文件1M的内容 if not content: break new_file.write(content) # 将读取的内容写入新文件 else: print('您输入的文件不存在') file.close() # 关闭备份文件 new_file.close() # 关闭新文件
-
csv文件的读写操作
-
csv文件的读取
import csv file = open('test.csv', mode='r', encoding='utf8') # csv.reader方法得到的结果是一个 reader 对象,它是一个可迭代对象 read = csv.reader(file) for i in read: print(i) # 以列表的形式输出 file.close()
-
csv文件的写入
import csv file = open('test.csv', mode='w', encoding='utf8', newline='') writer = csv.writer(file) writer.writerows([ # 以表格嵌套表格的形式写入文件 ['name', 'gender', 'age'], ['jack', 'male', 18], ['merry', 'female', 20] ]) file.close()
-
1.7.3 往内存中写入数据
-
StringIO对象
from io import StringIO, BytesIO s = StringIO() # 创建一个StringIO对象 print('hello world', file=s) # 将 hello world 写入内存s print('你好呀', file=s) # 将 你好呀 写入内存s print(file=s) # 将 \n 写入内存s print('今天心情真好', file=s) # 将 今天心情真好 写入内存s print(s.getvalue()) # 输出内存s存储的数据
-
BytesIO对象
from io import StringIO, BytesIO file = open('timg.jpg', 'rb') # 以二进制读取的方式打开文件 content = file.read() # 读取文件内容 b = BytesIO() # 创建一个BytesIO对象 b.write(content) # 将读取到的内容写入内存b print(b.getvalue()) # 输出内存b存储的数据
1.7.4 文件的序列化
-
序列化
定义:将python中的对象(字典、列表等)转为字符串或二进制,进行保存或者传递的过程。
-
序列化为字符串的方式
-
使用repr()
person = {'name': 'zhangsan', 'age': 18, 'height': 175.5} n = repe(person) # 将字典person转为字符串
-
使用str()
person = {'name': 'zhangsan', 'age': 18, 'height': 175.5} n = str(person) # 将字典person转为字符串
-
使用json模块
import json person = {'name': 'zhangsan', 'age': 18, 'height': 175.5} file = open('test.txt', 'w', encoding='utf8') # 打开文件 n = json.dumps(person) # 将对象转为字符串 file.write(n) # 将字符串写入文件 json.dump(person,file) # 将对象转为字符串并写入文件 file.close() # 关闭文件
-
-
序列化为二进制的方式
-
使用pickle模块
import pickle person = {'name': 'zhangsan', 'age': 18, 'height': 175.5} file = open('test.txt', 'wb') # 打开文件 n = pickle.dumps(person) # 将对象转为二进制 file.write(n) # 将二进制写入文件 pickle.dump(person,file) # 将对象转为二进制并写入文件 file.close() # 关闭文件
-
1.7.5 文件的反序列化
-
反序列化
定义:将字符串或者二进制转换成为Python对象,进行操作的过程。
-
将字符串反序列化为python对象
-
使用eval()
n = "{'name': 'zhangsan', 'age': 18, 'height': 175.5}" di = eval(n) # 将字符串转为python对象
-
使用json模块
import json file = open('test.txt', 'r', encoding='utf8') # 打开文件 n = file.read() # 读取文件的内容 di_1 = json.loads(n) # 将字符串转为python对象 di_2 = json.load(file) # 读取文件内容并转为python对象 file.close() # 关闭文件
-
-
将二进制反序列化为python对象
-
使用pickle模块
import pickle file = open('test.txt', 'r', encoding='utf8') # 打开文件 n = file.read() # 读取文件的内容 di_1 = pickle.loads(n) # 将字符串转为python对象 di_2 = pickle.load(file) # 读取文件内容并转为python对象 file.close() # 关闭文件
-
-
json模块和pickle模块的区别
-
json模块
json本质是字符串,主要使用就是在不同的平台之间传递数据
不是所有的 python 对象都能转换成为 json字符串
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NL8q1WA3-1664335392585)(.\Img\0254.png)]
-
pickle模块
pickle序列化是将对象按照一定的规则转换成为二进制保存,它不能跨平台传递数据。
pickle的序列化会将对象的所有数据都保存。
-
1.7.6 异常的介绍
-
try…except
-
语法
try: 可能出现错误的语句 except 错误类型: 处理语句
-
例如
try: file = open('test.txt', 'r') print('hello') print(1 / 0) file.close() except (FileNotFoundError, ZeroDivisionError) as e: print(f'出错了,错误是{e}')
-
1.8 常见模块
1.8.1 random模块
-
random模块
import random random.random() # 生成[0,1)的浮点数 random.choice(['hello', 'good']) # 从迭代对象中随机选取一个 random.sample(['hello', 'good'], 2) # 从迭代对象中随机选取2个 random.randint(1, 20) # 生成[1,20]的随机整数 random.randrange(1, 20) # 生成[1,20)的随机整数 li = [1,2,3,4,5,6] print(random.shuffle(li)) # 对列表中的数据无序输出
1.8.2 math模块
-
math模块
import math math.fabs(-10) # 负数的绝对值,返回的是浮点数 math.sin(math.pi / 6) # 求sinx的值 math.ceil(10.2) # 向上取整 math.ceil(-9.8) math.floor(2.9) # 向下取整 math.factorial(5) # 求阶乘 math.pow(2, 10) # 幂运算 2 ** 10 pow(2,10)
1.8.3 os模块
-
os模块
import math os.listdir() # 查看当前文件所在文件夹下的所有文件 os.chdir(path) # 查看路径下的的所有文件 os.chdir('../') # 查看当前文件的上一级文件夹下的所有文件 os.name # 操作系统的名字:win返回nt,类unix返回posix os.path.exists("test.txt") # 判断文件或文件夹是否存在 os.remove("text.txt") # 删除一个文件 os.mkdir(demo) # 创建一个文件夹 os.getcwd() # 获得当前文件的工作路径 os.rename('test.txt', 'ok.txt') # 对文件重命名 os.environ # 获得系统的配置环境 os.path.isdir('demo') # 判断是是否是文件夹 os.path.isfile('ok.txt') # 判断是否是文件 os.path.abspath('ok.txt') # 获得文件的绝对路径 os.path.splitext('2020.09.txt') # 将文件名分割成文名件前缀和后缀 dir(os) # 返回os的所有变量 os.cpu_count() # 返回cpu的个数 os.path.sep # 返回路径分隔符
1.8.4 time模块
-
time模块
import time time.time() # 获得当前时间戳 time.sleep(10) # 让线程暂停10秒
1.8.5 datetime模块
-
datetime模块
import datetime d = datetime.date(2020, 9, 2) print(d) # 返回指定时间:2020-09-02 print(d.ctime) # 返回:Wed Sep 2 00:00:00 2020 print(d.day) # 返回日期的天:2 print(d.month) # 返回日期的月:9 print(d.year) # 返回日期的年:2020 x = d.replace(2029, 5, 4) # 替换时间为:2029-05-04 datetime.date.today() # 返回当前日期 dt = datetime.datetime(2025, 1, 1, 18, 53, 45) print(dt) # 返回指定日期时间:2025-01-01 18:53:45 dtsn = datetime.datetime.now() print(dtsn) # 返回当前时间:2020-09-02 21:43:18.866635 print(dtdn.date()) # 返回日期 print(dtsn.time) # 返回时间 print(dtsn.hour) # 返回时间的小时:21 print(dtsn.minute) # 返回时间的分钟:43 print(dtsn.second) # 返回时间的秒数:18 print(dtsn.microsecond) # 返回时间的微秒:866635 print(dtsn + datetime.timedelta(days=0, hours=0, minutes=0, seconds=1)) # 返回时间:2020-09-02 21:43:19.866635
1.8.6 calendar模块
-
calendar模块
import calendar c = calendar.calendar(2020) print(c) # 返回的2020年的日历 c = calendar.TextCalendar() c.firstweekday = calendar.SUNDAY # 指定周天为一周的开始 print(c.formatyear(2020)) # 在每月后加入年份 print(c.formatmonth(2020, 9)) # 返回2020年9月的日历 c1 = calendar.HTMLCalendar() calendar.isleap(2000) # 判断年份是否是闰年 calendar.leapdays(1900, 1920) # 返回[1900,1920)年之间有几个闰年 calendar.monthrange(2020, 9) # 返回:(1,30),2020年9月第一天是周二,共30天 calendar.monthlen(2021, 2) # 返回2021年2月的天数
1.8.7 UUID
-
uuid
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gu8qVqvP-1664335392586)(.\Img\0255.png)]
1.9 面向对象基础
1.9.1 类和对象
-
类
类是对很多具有共同特性和行为(函数)的事物的统称,它是一个抽象的概念
-
对象
对象就是一个个具体的事物
-
例如
class Person: # 定义一个Person类 def __init__(self, name, age): # 在这个函数里定义属性 self.name = name self.age = age def eat(self): # 定义一个类的方法 print('人正在吃东西') p = Person('zhangsan', 18) # 创建一个对象p p.eat() # 使用对象调用类中的方法
1.9.2 魔法方法
-
_ _new_ _方法
class Person(object): def __new__(cls, *args, **kwargs): # 申请内存空间 return object.__new__(cls) # 重写了__init__方法 def __init__(self, name, age): self.name = name self.age = age # 1. 调用 __new__ 方法申请内存空间 # 2. 调用 __init__ 方法初始化 p = Person('张三', 18) print(p)
-
_ _init_ _方法
class Person: def __init__(self, name, age): self.name = name self.age = age # 1. 申请一段内存空间 __new__ # 2. 调用 __init__ 方法进行初始化;同时 __init__ 方法里的 self 指向创建好的内存空间 # 3. 把对象 p 也指向创建好的内存空间 p = Person('zhangsan', 18) print(p.name, p.age)
-
_ _del_ _方法
# 重写__del__方法 class Person: def __init__(self, name, age): self.name = name self.age = age def __del__(self): # 当删除对象时被调用 print("__del__被调用了!") p = Person("yang", 18) del p # 调用 __del__ 方法
-
_ _call_ _方法
# 重写__call__方法 class Person: def __init__(self, name, age): self.name = name self.age = age def __call__(self, *args, **kwargs): # 对象模拟函数的使用 print(self.name, self.age, args[0], kwargs["b"]) p = Person("yang", 18) p(1, 2, a=3) # 对象可像函数一样使用,等效于 Person.__call__(p, 1, 2, a=3, b=4) # Person.__call__()
-
_ _str_ _方法
# 不重写__str__方法 class Person: def __init__(self, name, age): self.name = name self.age = age p = Person('zhangsan', 18) # 创建一个对象 print(p) # 当输出对象时,会调用__str__方法,默认输出类名和对象地址 # 重写__str__方法 class Person: def __init__(self, name, age): self.name = name self.age = age def __str__(self): # 重写 __str__ 方法 return 'yes' p = Person('zhangsan', 18) # 创建一个对象 print(p) # 调用 __str__ 方法,输出 yes
-
_ _repr_ _方法
# 不重写__repr__方法 class Person: def __init__(self, name, age): self.name = name self.age = age p = Person("yang", 18) # 创建一个对象 print(repr(p)) # 调用__repr__方法,默认输出类名和对象地址 # 重写__repr__方法 class Person: def __init__(self, name, age): self.name = name self.age = age def __repr__(self): # 当对象被转为解释器可读的形式时,将会调用 return "yes" p = Person("yang", 18) # 创建一个对象 print(repr(p)) # 调用__repr__方法,输出 yes
-
_ _str_ _方法与_ _repr_ _方法的区别
class Person: def __init__(self, name, age): self.name = name self.age = age def __str__(self): return f"{self.name}" p1 = Person("yang", 18) p2 = Person("ssun", 18) print([p1, p2]) # 输出 [<__main__.Person object at 0x000002CA66FD4700>, # <__main__.Person object at 0x000002CA670B8040>] class Person: def __init__(self, name, age): self.name = name self.age = age def __repr__(self): return f"{self.name}" p1 = Person("yang", 18) p2 = Person("ssun", 18) print([p1, p2]) # 输出 [yang, ssun]
-
_ _int_ _、_ _getitem_ _、_ _setitem_ _方法
class Person: def __init__(self, name, age): self.name = name self.age = age def __int__(self): # 对象强转为int类型时调用 return self.age def __getitem__(self, item): # 使对象可像字典一样获取数据 return self.__dict__[item] def __setitem__(self, key, value): # 使对象可像字典一样修改数据 self.__dict__[key] = value p = Person("yang", 18) print(int(p)) # 调用__int__方法 print(p["name"]) # 调用__getitem__方法 p["height"] = 170 # 调用__setitem__方法 print(p["height"])
-
_ _add_ _、_ _sub_ _、_ _mul_ _、_ _truediv_ _、_ _gt_ _、_ _lt_ _、_ _ge_ _、_ _le_ _方法
class Person: def __init__(self, name, age): self.name = name self.age = age def __add__(self, other): # 当对象做加法运算时调用 return self.age + other def __sub__(self, other): # 当对象做减法运算时调用 return self.age - other def __mul__(self, other): # 当对象做乘法运算时调用 return self.age * 2 def __truediv__(self, other): # 当对象做除法运算时调用 return self.age / 2 def __gt__(self, other): # 当对象做大于运算时调用 return self.age > other def __lt__(self, other): # 当对象做小于运算时调用 return self.age < other def __ge__(self, other): # 当对象做大于等于运算时调用 return self.age >= other def __le__(self, other): # 当对象做小于等于运算时调用 return self.age <= other p = Person("yang", 18) print(p + 2) # 调用__add__方法 print(p - 2) # 调用__sub__方法 print(p * 2) # 调用__mul__方法 print(p / 2) # 调用__truediv__方法 print(p > 18) # 调用__gt__方法 print(p < 18) # 调用__lt__方法 print(p >= 18) # 调用__ge__方法 print(p <= 18) # 调用__le__方法
1.9.3 身份运算符
-
身份运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-14vEvNyo-1664335392587)(.\Img\0256.png)]
-
_ _eq_ _方法
class Person: def __init__(self, name, age): self.name = name self.age = age def __eq__(self, other): # 当对象使用 == 时调用 return self.name == other.name p1 = Person("yang", 18) p2 = Person("yang", 19) print(p1 == p2) # 调用__eq__方法
1.10 面向对象高级
1.10.1 私有属性和方法
-
私有属性和方法的定义
class Person: def __init__(self, name, age, salary): self.name = name self.age = age self.__salary = salary # 定义私有属性 def __test(self): return self.__salary # 定义私有方法
-
访问私有属性和方法
-
直接访问(不建议使用)
class Person: def __init__(self, name, age, salary): self.name = name self.age = age self.__salary = salary # 定义私有属性 def __test(self): return self.__salary # 定义私有方法 p = Person("yang", 18, 10000) print(p._Person__salary) # 在外部对象访问类中的私有属性 print(p._Person__test()) # 在外部对象访问类中的私有方法
-
间接访问
class Person: def __init__(self, name, age, salary): self.name = name self.age = age self.__salary = salary def set_salary(self, salary): self.__salary = salary def get_salary(self): return self.__salary p = Person("yang", 18, 10000) p.set_salary(20000) # 调用set_salary方法,修改私有属性 print(p.get_salary()) # 调用get_salary方法,获取私有属性
-
1.10.2 实例属性和类属性
-
实例属性和类属性
class Person: type = "人类" # 类属性,实例对象和类对象可访问 def __init__(self, name, age): self.name = name # 实例属性 self.age = age
-
类属性的访问和修改
class Person: type = "人类" def __init__(self, name, age): self.name = name self.age = age p = Person("yang", 18) # 创建实例对象 print(p.type) # 实例对象访问类属性 print(Person.type) # 类对象访问类属性 Person.type = "非人类" # 类属性只能通过类对象来修改
1.10.3 实例方法、静态方法、类方法
-
实例方法
class Person: type = "人类" def __init__(self, name, age): self.name = name self.age = age def get_name(self): # 实例方法,即可访问实例属性,也可访问类属性 return self.name, Person.type p = Person("yang", 18) print(p.get_name()) # 实例对象调用实例方法 print(Person.get_name(p)) # 类对象调用实例方法
-
静态方法
class Person: type = "人类" def __init__(self, name, age): self.name = name self.age = age self.__class__.type = "非人类" @staticmethod # 定义为静态方法,不访问任何资源 def test(): return "我是个植物人" p = Person("yang", 18) print(p.test()) # 实例对象调用静态方法 print(Person.test()) # 类对象调用静态方法
-
类方法
class Person: type = "人类" def __init__(self, name, age): self.name = name self.age = age @classmethod # 定义类方法,只访问了类属性 def get_type(cls): return cls.type p = Person("yang", 18) print(p.get_type()) # 实例对象调用类方法 print(Person.get_type()) # 类属性调用类方法
1.10.4 单例设计模式
-
单例设计模式
class Person(object): __address = None # 定义类属性 __flag = True def __new__(cls, *args, **kwargs): # 重写__new__方法,只申请一次内存 if cls.__address is None: cls.__address = object.__new__(cls) return cls.__address def __init__(self, name, age): # 初始化,只会初始化一次 if self.__flag: self.name = name self.age = age self.__flag = False p1 = Person("yang", 18) # 创建实例对象 p2 = Person("ssun", 18) print(p1 is p2) # 输出 True print(p1.name) # 输出 yang
1.10.5 继承
-
继承的基本语法
class Person: def __init__(self, name, age): self.name = name self.age = age def get_name(self): return self.name class Student(Person): # 定义子类,继承父类 pass p = Student("yang", 18) # 创建实例对象,可使用父类的属性 print(p.name) # 实例对象访问父类的属性 —————————————————————————————————————————————————————————————————————————————— class Person: def __init__(self, name, age): self.name = name self.age = age class Student(Person): def __init__(self, name, age, school, user_id): # 重写父类中的方法 super(Student, self).__init__(name, age) # 使用父类中的属性 self.school = school # 定义自己的属性 self.user_id = user_id p = Student("yang", 18, "qust", 1) print(p.name, p.user_id) # 输出 yang 1
-
父类的私有成员子类不能继承
class Person: def __init__(self, name, age): self.name = name self.age = age self.__salary = 10000 # 定义私有属性 def __test(self): # 定义私有方法 return self.__salary class Student(Person): # 定义子类 pass s = Student("yang",18) # 创建子类的实例对象 print(s.name) # 子类的实例对象访问父类属性 print(s.__salary) # 报错,子类不能继承父类的私有属性 s.__test() # 报错,子类不能继承父类的私有方法
-
多重继承
class A: # 定义一个父类A def test(self): # 定义A中的实例方法test print("test_A") class B: # 定义一个父类B def test(self): # 定义B中的实例方法test print("test_B") def demo(self): # 定义B中的实例方法demo print("demo_B") class C(A, B): # 定义子类C,继承A、B类 pass c = C() # 创建实例对象c c.demo() # 输出 demo_B c.test() # 输出 test_A print(C.__mro__) # 表示子类C调用父类成员时寻找父类的先后顺序 # __mro__只能由类对象来调用
1.10.6 多态
-
使用场景
class Dog: # 定义父类Dog def __init__(self, name, color): self.name = name self.color = color def dog_work(self): print(f"{self.color}的{self.name}正在工作!") class PoliceDog(Dog): # 定义子类PoliceDog,继承Dog def dog_work(self): print(f"{self.color}的{self.name}是警犬,正在攻击敌人!") class SearchaDag(Dog): # 定义子类SearchaDag,继承Dog def dog_work(self): print(f"{self.color}的{self.name}是搜救犬,正在搜救同伴们!") class GuideDog(Dog): # 定义子类GuideDog,继承Dog def dog_work(self): print(f"{self.color}的{self.name}是导盲犬,正在为盲人引路!") def work(dog): # 定义一个函数来调用各子类 if isinstance(dog,Dog): # 判断传入的参数对象是否指定类(或其子类)实例化出的对象 dog.dog_work() else: # 自定义异常 raise TypeError("参数必须是Dog或者它子类创建出来的实例对象") pd = PoliceDog("大黄", "黑色") # 创建实例对象 sd = SearchaDag("小黑", "白色") gd = GuideDog("小白", "黄色") work(pd) # 输出 黑色的大黄是警犬,正在攻击敌人! work(sd) # 输出 白色的小黑是搜救犬,正在搜救同伴们! work(gd) # 输出 黄色的小白是导盲犬,正在为盲人引路! work(12) # 报错,输出 参数必须是Dog或者它子类创建出来的实例对象
1.10.7 property的使用
-
property的类属性
class Person: def __init__(self, name, age, salary): self.name = name self.age = age self.__salary = salary def get_salary(self): return self.__salary def set_salary(self, salary): self.__salary = salary # 定义类属性,用于私有属性__salary的快速访问和修改 my_salary = property(fget=get_salary, fset=set_salary, doc="") p = Person("yang", 18, 10000) # 创建实例对象 print(p.my_salary) # <==> p.get_salary() p.my_salary = 20000 # <==> p.set_salary(20000)
-
property的装饰器
class Person: def __init__(self, name, age, salary): self.name = name self.age = age self.__salary = salary # 定义私有属性 @property def money(self): # 定义此方法可被快速访问 return self.__salary @money.setter # 定义此方法可通过指定的名字进行修改 def money(self, salary): self.__salary = salary p = Person("yang", 18, 10000) print(p.money) # 访问money(self) p.money = 20000 # 访问money(self,salary)
1.10.8 常见的内置属性
-
_ _class_ _、_ _dict_ _、_ _module_ _、_ _dos_ _、
class Person: """ 这是一个Person类 """ type = "人类" # 定义类属性 def __init__(self, name, age): self.name = name self.age = age __class__.type = "非人类" # 对类属性进行修改 p = Person("yang", 18) print(p.__class__.type) # 通过__call__获取类对象 print(p.__dict__) # 将对象转为字典,数据以key-values存储 print(p.__module__) # 获得对象对应的模块名 print(p.__doc__) # 获得类的介绍
1.10.9 异常
-
处理异常
try: x = 1 / 0 except Exception as e: # Exception处理所有异常 print(e)
try: y = "1" + 1 x = 1 / 0 except (TypeError, ZeroDivisionError) as e: # 使用元组处理多种异常 print(e)
try: y = "1" + 1 x = 1 / 0 except TypeError as e: # 使用多个except处理异常 print(e) except ZeroDivisionError as e: print(e)
try: x = 1 / 0 except ZeroDivisionError as e: print(e) finally: # 无论有没有异常,都将会执行finally print("我总会被执行!")
-
常见的错误类型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dMyDNRJC-1664335392588)(.\Img\0257.png)]
-
自定义异常
class PwdlenError(Exception): # 自定义一个异常类,并继承Exception def __init__(self, x, y): self.x = x self.y = y def __str__(self): # 触发异常,将输出的内容 return f"密码长度需要在{self.x}~{self.y}之间" def check_password(password): # 定义一个方法用于核验密码规范 if len(password) >= 6 and len(password) <= 12: print("密码合乎规范!") else: print("密码不合乎规范!") e = PwdlenError(6, 12) # 创建异常类的实例对象 raise e # 将会调用类中的 __str__ 方法 password = input("请输入(6~12)位的密码:") try: check_password(password) # 调用check_password()核验密码 except PwdlenError as e: print(e) # 打印错误提示
-
with关键字的使用
class MyManager: # 自定义个类来管理上下文 def __init__(self, file, mode, encoding): self.file = file self.mode = mode self.encoding = encoding def __enter__(self): #重写__enter__方法 print("__enter__") return self def __exit__(self, exc_type, exc_val, exc_tb): # 重写__exit__方法 print("__exit__") self.close() def close(self): print("文件关闭了!") def create_mymanager(file, mode, encoding): # 实例化对象 my_manager = MyManager(file, mode, encoding) return my_manager # 首先执行with语句,然后调用__enter__方法,当出现异常或with代码块执行完,调用__exit__方法 with create_mymanager("text.txt", "r", encoding="utf8") as m: # with上下文管理器 print(m)
with open("text.txt", "r", encoding="utf8") as file: x = file.read() print(x) # <==> file = open("text.txt","r",encoding="utf8") # file.__enter__ # 当出现异常或with代码块执行完会调用 __exit__方法
注意:with不具有处理异常的能力
1.10.10 模块和包
-
导入模块(5种)
-
import 模块名
import random # 导入pytho中的库模块
-
from 模块名 import 功能名
from random import randint # 导入random模块下的方法randint
-
**from 模块名 import ***
from random import * # 导入random模块下的所有方法和类
-
import 模块名 as 别名
import random as rd # 导入random模块并为其起一个别名为rd
-
from 模块名 import 功能名
from random import randint as ri # 导入random模块下的方法randint # 并为其起一个别名为ri
-
-
搜索模块的路径
print(sys.path) # 模块的搜索路径存储在变量sys.path
注:通常将模块和包放于项目路径下
-
_ _name_ _测试模块
print(__name__) # 在模块中将输出__main__ import 模块 # 在非模块中运行将输出模块名
-
_ _all_ _在模块中的使用
# 在模块中使用__all__ # 模块文件 model.py __all__ = ["test","a"] def test(): print("test") a = 10 b = 20 def demo(): print("demo") ______________________________________________________________________________ # 导入模块文件 model.py from model import * # 导入模块model print(test()) # 可调用模块中的test() print(a) # 可调用模块中的a print(b) # 不可调用模块中的b print(demo) # 不可调用模块中的demo()
-
导入包中的模块
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MaHpiQVT-1664335392589)(.\Img\0258.png)]
-
import 包名.模块名
# 导入包中的模块 import User.userinfo
-
from 包名 import 模块名
# 导入包中指定的模块 from User import userinfo
-
**from 包名 import ***
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mvkVUdX5-1664335392590)(.\Img\0259.png)]
# 导入包下所有模块 # 当导入包下所有模块,首先会访问__init__.py中的__all__ # __init__.py __all__ = ["userinfo"] ___________________________________________________________________________ # 导入User包下模块 from User import * print(userinfo.a) # 会调用userinfo模块下的a print(useraddress.a) # 报错,因为__init__.py中的__all__位将其包含
-
1.11 正则表达式
1.11.1 正则查找
-
search()
# search()只匹配一次,查找的是整个字符串 # 匹配到的结果是一个 re.Match 类型的对象 import re n = re.search(r"x", "sedfxfg") print(n)
-
match()
# match()只匹配一次,是从头匹配,若开头不匹配则返回None # 匹配到的结果是一个 re.Match 类型的对象 import re n = re.match(r"x", "xdfhxsdsxsdfsdf") print(n)
-
fullmatch()
# 对整个字符串的完整匹配 import re n = re.fullmatch(r"s\d+r", "s1234r") # 等效于 re.match(r"^s\d+r$", "s1234r") print(n)
-
findall()
# 匹配字符串中满足正则表达式的所有子串,并返回一个列表,若无匹配结果,返回空列表 import re n = re.findall(r"\d+", "s12ddds45qw123q") print(n)
-
finditer()
# 匹配字符串中满足正则表达式的所有子串,并返回一个迭代器,其每个元素都为re.Match 类型的对象 import re n = re.finditer(r"\d+", "sd12sdaaw45awe123wq") print(list(n))
1.11.2 re.Match类型
-
re.Match类型
当调用re.search()、re.match()、re.finditer()得到结果,
并对其进行迭代获取的数据的数据类型是re.Match类型
-
属性和方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1vfviQLM-1664335392591)(.\Img\0260.png)]
import re # string、re、start()、end() a = re.search(r"\d+", "a23kdfjl123askjd456") print(a.string) # 匹配的源字符串 print(a.re) # 正则表达式规则,<==>re.compile("\\d+") print(a.start()) # 匹配到结果的开始下标 print(a.end()) # 匹配到结果的最后下标 # 使用()进行分组,使用group()获取分组匹配的结果 b = re.match(r".*c(\d+).*r(\d+)", "abc13def456r789qwqeqwr") print(b.group(0)) # 满足正则表达式的子串 print(b.group(1)) # 返回第1组的数据 print(b.group(2)) # 返回第2组的数据 # 使用(?P<name>)为分组起别名,可使用别名来使用分组 c = re.match(r".*c(?P<a>\d+).*r(\d+)", "ablc13def456r789qwqeqwr") print(c.start("a")) print(c.end("a")) print(c.group("a")) # groupdict()以字典的形式保存分组数据 d = re.match(r".*c(?P<a>\d+).*r(?P<b>\d+)", "ablc13def456r789qwqeqwr") print(d.groupdict()) # 以字典的形式保存分组的数据,key为分组别名 print(d.groupdict()["b"]) # 获取字典中key为b的数据 # span() e = re.search(r".*c(?P<a>\d+).*r(?P<b>\d+)", "ablc13def456r789qwqeqwr") print(e.span("b")) # 以元组的形式返回别名为b分组的开始下标和结束下标
1.11.3 re.complie的使用
-
re.complie
p = re.complie(r"\d+") print(type(p)) # 返回p的类型为 <class 're.Pattern'> print(p.search("lkj123lk")) # 返回<re.Match object; span=(3, 6), match='123'>
1.11.4 正则模式
-
非打印字符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EKvKTTrG-1664335392592)(.\Img\0261.png)]
-
特殊字符
若要匹配这些特殊字符,必须首先使字符"转义
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XjZget1B-1664335392592)(.\Img\0262.png)]
-
定位符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V8WcZwAL-1664335392593)(.\Img\0263.png)]
-
限定符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9pecZPPJ-1664335392594)(.\Img\0264.png)]
-
正则表达式
-
标点符号
# . :表示匹配除了换行符以外的任意字符 # * :表示前面字符出现的任意次数,等效于{0,} # ? :表示前面字符最多出现一次,等价于{,1};可将贪婪模式转换为非贪婪模式 # + :表示前面字符至少出现一次,等价于{1,} # [] :表示单个字符的取值范围,常结合 - 配合使用 # - :表示范围 # {m,n} :表示元素出现 m ~ n 次 # () :用来进行分组 # (?P<name>) :给分组起别名 # (?:) :表示一个非捕获分组 # | :用来表示取值范围,通常配合 () 使用 # ^ :用来表示以指定的字符开始 # $ :用来表示以指定的字符结束
-
字母的转义
# \r :匹配回车 # \n :匹配换行 # \t :匹配制表符 # \s :匹配非打印字符 # \S :匹配打印字符 # \w :匹配数字、字母、下划线,等效于[0-9a-zA-Z_] # \W :匹配非数字、字母、下划线,等效于[^0-9a-zA-Z_] # \d :匹配数字,等效于[0-9] # \D :匹配非数字,等效于[^0-9] # \u :表示Unicode编码,匹配汉字[\u4E00-\u9FA5]
-
1.11.5 正则替换
-
语法
# 参数 # pattern:正则表达式 # repl:替换的字符串或函数 # string:被替换的原字符串 # count:模式匹配后的替换的最大次数,默认值为0,表示替换所以匹配项 re.sub(pattern,repl,string,count=0)
-
re.sub()
# 将数字替换为字母x print(re.sub(r'\d+', 'x', 'h43df19la28f')) # 提取电话号码 print(re.sub(r'\D', '', "2004-959-559 # 这是一个电话号码")) def test(arg): return str(int(arg.group("num")) * 2) # 将字符串中的数字替换成其数值的两倍 b = re.sub(r'(?P<num>\d+)', test, 'h43df19la28f') print(b) # 输出 h86df38la56f
1.11.6 贪婪模式和非贪婪模式
-
贪婪模式
# 贪婪模式是尽可能多个匹配 x = re.search(r'h(.+)(\d+)t(.{2,4})(\d+)', 'h6789t123456') print(x.group(1)) # 输出 678 print(x.group(2)) # 输出 9 print(x.group(3)) # 输出 1234 print(x.group(4)) # 输出 56
-
非贪婪模式
# 在 * ? + {n,m}后加上?,可将贪婪模式转为非贪婪模式 # 非贪婪模式是尽可能少的匹配 x = re.search(r'h(.?)(\d+)t(.{2,4}?)(\d+)', 'ht6789t123456') print(x.group(1)) # 输出 t print(x.group(2)) # 输出 6789 print(x.group(3)) # 输出 12 print(x.group(4)) # 输出 3456
1.11.7 正则修饰符
-
修饰符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xpGptmGT-1664335392595)(.\Img\0325.png)]
-
修饰符的使用
# re.I print(re.search(r'H', 'hello', re.I)) # 输出 <re.Match object; span=(0, 1), match='h'> # re.S print(re.search(r'.', '\n', re.S)) # 输出 <re.Match object; span=(0, 1), match='\n'> # re.M print(re.findall(r'\w+$', 'hello world\nyes no\nok\nhi', re.M)) # 输出 ['world', 'no', 'ok', 'hi']
1.12 迭代器和生成器
1.12.1 迭代器
-
常见的可迭代对象
字符串、列表、元组、字典、集合、range()、map()、filter
-
判断一个对象是否是可迭代对象
from collections.abc import Iterable print(isinstance([1, 2, 3], Iterable)) # 输出 True
-
可迭代对象的本质
可迭代对象通过 _ _iter_ _ 方法向我们提供一个迭代器,我们在迭代一个可迭代对象的时候,实际上就是先获取该对象提供的一个迭代器,然后通过这个迭代器来依次获取对象中的每一个数据。
那么也就是说,一个具备了 _ _iter_ _ 方法的对象,就是一个可迭代对象。 -
什么是迭代器
一个实现了 _ _iter_ _ 方法和_ _next_ _ 方法的对象就是迭代器
-
判断一个对象是否是迭代器
n=[1,2,3] # 调用__iter__方法 print(n.__iter__()) # 输出 <list_iterator object at 0x0000026205B886D0> # 调用内置函数iter() print(iter(n)) # 输出 <list_iterator object at 0x0000026205B886D0> # 使用isinstance() print(isinstance(iter(n),Iterable)) # 输出 True
-
自定义迭代器
# 自定义迭代器 class Demo(object): def __init__(self, n): self.n = n self.count = 0 def __iter__(self): return self def __next__(self): self.count += 1 if self.count <= self.n: return self.count - 1 raise StopIteration d =Demo(5) for i in d: print(i) # 输出 0 1 2 3 4
-
使用迭代器计算斐波那契数列
class Fibonacci: def __init__(self, n): self.n = n self.num1 = self.num2 = 1 self.count = 0 def __iter__(self): return self def __next__(self): self.count += 1 x = self.num1 if self.count <= self.n: self.num1, self.num2 = self.num2, self.num1 + self.num2 return x raise StopIteration fib = Fibonacci(12) for f in fib: print(f) # 输出 1 1 2 3 5 8 13 21 34 55 89 144
-
迭代器和列表的区别
列表是将整个给数据保存在内存中,占用空间,操作熟读快
迭代器不将数据保存在内存中,布占用空间,操作速度相对慢
1.12.2 生成器
-
什么是生成器
生成器是一类特殊的迭代器
-
创建生成器
# 方法一 g = (i * 10 for i in range(5)) print(g) # 输出 <generator object <genexpr> at 0x000002176054AD60> for i in g: print(i) # 输出 0 10 20 30 40
# 方法二 def Demo(n): i = 0 while i < n: yield i * 10 i = i * 10 g = Demo(5) print(g) # 输出 <generator object Demo at 0x0000026CE196AD60> for i in g: print(i) # 输出 0 10 20 30 40 print(next(g)) # 输出 0 print(next(g)) # 输出 10 print(next(g)) # 输出 20 print(next(g)) # 输出 30 print(next(g)) # 输出 40
-
生成器求斐波那契数列
def fibonacci(n): num1 = num2 = 1 count = 0 while count < n: yield num1 num1, num2 = num2, num1 + num2 count += 1 fib = fibonacci(12) print(fib) # 输出 <generator object fibonacci at 0x0000020BCAB89E40> for i in fib: print(i) # 输出 1 1 2 3 5 8 13 21 34 55 89 144
1.13 加密方式
1.13.1 base64编码
-
base64编码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I85UuADZ-1664335392596)(.\Img\0326.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wbx9UiUP-1664335392597)(.\Img\0327.png)]
-
实现base64编码
import base64 s = "魔狼" # 将字符串转为二进制 s_b = s.encode() print(s_b) # 输出 b'\xe9\xad\x94\xe7\x8b\xbc' # 将二进制进行base64编码 be64_v = base64.b64encode(s_b) print(be64_v) # 输出 b'6a2U54u8' # 对base64编码后的字符串进行解码 bde64_v=base64.b64decode(be64_v) print(bde64_v) # 输出 b'\xe9\xad\x94\xe7\x8b\xbc'
1.13.2 常见的加密算法
-
加密方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JRhgKgEX-1664335392598)(.\Img\0328.png)]
-
MD5加密
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZK9vLwUr-1664335392599)(.\Img\0329.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JDtZI6rP-1664335392599)(.\Img\0331.png)]
-
MD5加密的实现
import hashlib s = "魔狼" # 将字符串转为二进制 s_b = s.encode(encoding="utf8") print(s_b) # 输出 b'\xe9\xad\x94\xe7\x8b\xbc' # 创建MD5对象 hl = hashlib.md5() # 对转为二进制的字符串进行md5加密 hl.update(s_b) # 获取对字符串进行加密后的密文 s_md5 = hl.hexdigest() print(s_md5) # 输出 2b84329c56da0f383cbabf85c498f215
-
SHA加密
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FcBpomNl-1664335392600)(.\Img\0330.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nANuuuyU-1664335392601)(.\Img\0332.png)]
-
SHA加密的实现
import hashlib s = "魔狼" s_b = s.encode(encoding="utf8") print(s_b) # 输出 b'\xe9\xad\x94\xe7\x8b\xbc' # 对转为二进制的字符串进行SHA加密,不同的SHA加密方式密文长度不同 h_s1 = hashlib.sha1(s_b) h_s224 = hashlib.sha224(s_b) h_s256 = hashlib.sha256(s_b) print(h_s1.hexdigest()) # 输出 7631e6d3f5304af63ff02dbf05da1e0f18e8685f print(h_s224.hexdigest()) # 输出 66072ff0456a11273ca3c6b393a9390f838ce06e07139445886a6752 print(h_s256.hexdigest()) # 输出 ea975dcc88a3efd81cdb1de1838b92d0391a80fb32aefc2d9ac2f7e8d6d94907
1.14 网络通信
1.14.1 ip地址
-
ip地址分类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ybmjCkVV-1664335392603)(.\Img\0333.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LWY7GO71-1664335392604)(.\Img\0334.png)]
1.14.2 upd发送、接收消息
-
upd发送消息
import socket # 创建一个基于udp的socket链接 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 调用sendto()方法给指定的主机和端口发送信息 # 发送的数据需要转为二进制 s.sendto("你好".encode("utf8"), ("10.11.16.228", 8090)) # 接受的数据也是二进制 data = s.recv(1024).decode("utf8") print(data) s.close()
-
upd接收消息
# 被动的接受消息需要绑定端口 s.bind(("10.11.16.134", 9090)) while 1: # recvfrom接收的是个元组 # 第0个元素是对方发送的内容 # 第2个元素是对方的地址和端口所组成的元组 data,address=s.recvfrom(1024) print(data) print(address)
1.14.3 基于udp的聊天
-
实现
import socket, threading # 发送消息 def send_msg(): send_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) ip = input('请输入您要发送的目标IP地址:') port = int(input('请输入对方的端口号:')) while True: content = input('请输入您要发送的内容:') if content == 'stop': break send_socket.sendto(content.encode('utf8'), (ip, port)) send_socket.close() # 接收消息 def recv_msg(): recv_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) recv_socket.bind(('10.11.62.66', 8000)) file = open('msg.txt', 'w', encoding='utf8') while True: data, address = recv_socket.recvfrom(1024) print(f'接收到来自{address[0]}:{address[1]}的消息,\ 内容是:{data.decode("utf8")}', file=file) # 将缓冲区的数据写入文件中,并清空缓冲区 file.flush() t1 = threading.Thread(target=send_msg) t2 = threading.Thread(target=recv_msg) t1.start() t2.start()
1.14.4 多任务
-
实现
import time, threading def dance(): for i in range(100): print('我正在跳舞') time.sleep(0.2) def sing(): for i in range(100): print('我正在唱歌') time.sleep(0.2) t1 = threading.Thread(target=dance) t2 = threading.Thread(target=sing) t1.start() t2.start()
1.14.5 tcp发送、接收消息
-
tcp发送消息
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # tcp 发送消息之前,必须要先建立连接 s.connect(('10.11.62.66',6060)) # 将数据(二进制)发送出去 s.send('下午好'.encode('utf8')) s.close()
-
tcp接收消息
import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 绑定 IP地址和端口号 s.bind(('10.11.62.66', 6060)) # 把socket变成一个被动的socket s.listen(128) # 接收客户端的请求,得到的结果是一个元组 # 元组里第0个元素是客户端的socket连接 # 元组里第1个元素是客户端的IP地址和端口号 client_socket, client_addr = s.accept() # 从客户端的socket里获取到客户端发送过来的数据 content = client_socket.recv(1024).decode('utf8') print(f'接收到了来自{client_addr[0]}:{client_addr[1]}的请求,内容是:{content}') s.close()
1.14.6 文件下载
-
服务器
import socket, os server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 127.0.0.1 表示的是本机,如果绑定的是这个IP地址,只能本机访问,别的主机不能访问 # 0.0.0.0 表示所有可用的地址 server_socket.bind(('0.0.0.0', 9090)) # 把socket变成一个被动的socket server_socket.listen(128) while True: # 获取客户端发送过来的数据 client_socket, client_addr = server_socket.accept() file_name = client_socket.recv(1024).decode('utf8') # 根据客户端的请求来读取文件,并将读取到的数据发送到客户端 if os.path.exists(file_name): file = open(file_name, 'rb') content = file.read() client_socket.send(content) client_socket.close()
-
客户端
import socket client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 与服务器建立链接 client_socket.connect(('127.0.0.1', 9090)) file_name = input('请输入您要下载的文件名:') # 向服务器发送请求数据 client_socket.send(file_name.encode('utf8')) # 创建文件用以保存服务器返回的数据 file = open(file_name, 'wb') while True: data = client_socket.recv(1024 * 1024 * 10) if not data: break file.write(data) client_socket.close() file.close()
1.14.7 HTTP服务器
-
实现
import socket http_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) http_socket.bind(('0.0.0.0', 8080)) http_socket.listen(129) while True: client_socket, client_address = http_socket.accept() data = client_socket.recv(1024).decode('utf8') print(f'接收到了来自{client_address[0]}:{client_address[1]}的数据,内容是:') print(data) # 先返回HTTP响应头,每个响应头后面都要有换行 client_socket.send('HTTP/1.1 200 OK\n'.encode('utf8')) client_socket.send('Content-Type: text/html;\ charset=utf-8\n'.encode('utf8')) # 响应头结束以后,再发送一个换行,用来表示响应头已经结束,接下来再接收到的数据就是内容 client_socket.send('\n'.encode('utf8')) # 返回数据 # client_socket.send('hello'.encode('utf8')) # client_socket.send('<h1 style="color:red;">hello</h1>'.encode('utf8')) file = open('test.html', 'rb') content = file.read() client_socket.send(content) file.close() client_socket.close()
1.15 操作数据库
1.15.1 sqlite数据库
-
操作sqlite数据库
import sqlite3 # 与sqlite数据库建立链接 conn = sqlite3.connect("data.sqlite") # 执行sql语句,创建表 conn.execute("create table if not exists student \ (id int primary key,name vachar(16))") # 执行insert语句 conn.execute("insert into student(id,name) values(1,'yang'),(2,'lang')") # 执行select,返回一个Cursor对象 cursor = conn.execute("select * from student") print(cursor.fetchall()) # 输出 [(1, 'yang'), (2, 'lang')] cursor.close() conn.commit() conn.close()
1.15.2 pymysql
-
pymysql操作数据库
pip install pymysql pip install mysqlclient
import MySQLdb # 与mysql数据库建立链接 conn = MySQLdb.connect(host="127.0.0.1", user="root", password="123456",\ database="text", port=3306, charset="utf8") # 获取游标对象,通过游标对象来操作数据库 cursor = conn.cursor() # 执行sql语句,创建表 cursor.execute("create table if not exists studnet\ (id int primary key,name varchar(16))") # 执行insert语句 cursor.execute("insert into studnet values(1,'yang'),(2,'lang')") # 执行select语句,返回的结果是影响的记录数 result = cursor.execute("select * from studnet") print(result) # 输出 2 print(cursor.fetchall()) # 输出 ((1, 'yang'), (2, 'lang')) conn.commit() conn.close()
1.15.3 避免sql注入
-
避免sql注入
name = input("请输入用户名:") password = input("请输入密码:") # 执行sql语句 # 当name值以 "# 结尾时,就会发生sql注入的风险F cursor.execute(f'select * from user \ where name="{name}" and password="{password}"') # 避免sql注入 sql = 'select * from user where name=%s and password=%s' cursor.execute(sql, (name, password))
1.15.4 sqlalchemy
-
sqlalchemy操作数据库
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, create_engine from sqlalchemy.orm import sessionmaker Base = declarative_base() class User(Base): __tablename__ = "user" id = Column(Integer, primary_key=True) name = Column(String) password = Column(String) def __repr__(self): return f"id={self.id},name={self.name},password={self.password}" # 链接数据库 conn_info = "mysql+pymysql://root:123456@127.0.0.1:3306/text" engine = create_engine(conn_info, encoding="utf8") # 使用连接引擎创建一个session session = sessionmaker(bind=engine)() # 添加数据 s1 = User(id=1, name="yang", password="123456") session.add(s1) s2 = User(id=2, name="lang", password="456123") s3 = User(id=3, name="ssun", password="741258") session.add_all([s2, s3]) # 删除数据 user_1 = session.query(User).filter_by(id=3).first() session.delete(user_1) # 更新数据 session.query(User).filter_by(id=2).update({"name":"ssun"}) # 查询数据 print(session.query(User).all()) print(session.query(User).filter_by(name="ssun").first()) session.commit()
的数据,内容是:')
print(data) # 先返回HTTP响应头,每个响应头后面都要有换行 client_socket.send('HTTP/1.1 200 OK\n'.encode('utf8')) client_socket.send('Content-Type: text/html;\ charset=utf-8\n'.encode('utf8')) # 响应头结束以后,再发送一个换行,用来表示响应头已经结束,接下来再接收到的数据就是内容 client_socket.send('\n'.encode('utf8')) # 返回数据 # client_socket.send('hello'.encode('utf8')) # client_socket.send('<h1 style="color:red;">hello</h1>'.encode('utf8')) file = open('test.html', 'rb') content = file.read() client_socket.send(content) file.close() client_socket.close()
1.15 操作数据库
1.15.1 sqlite数据库
-
操作sqlite数据库
import sqlite3 # 与sqlite数据库建立链接 conn = sqlite3.connect("data.sqlite") # 执行sql语句,创建表 conn.execute("create table if not exists student \ (id int primary key,name vachar(16))") # 执行insert语句 conn.execute("insert into student(id,name) values(1,'yang'),(2,'lang')") # 执行select,返回一个Cursor对象 cursor = conn.execute("select * from student") print(cursor.fetchall()) # 输出 [(1, 'yang'), (2, 'lang')] cursor.close() conn.commit() conn.close()
1.15.2 pymysql
-
pymysql操作数据库
pip install pymysql pip install mysqlclient
import MySQLdb # 与mysql数据库建立链接 conn = MySQLdb.connect(host="127.0.0.1", user="root", password="123456",\ database="text", port=3306, charset="utf8") # 获取游标对象,通过游标对象来操作数据库 cursor = conn.cursor() # 执行sql语句,创建表 cursor.execute("create table if not exists studnet\ (id int primary key,name varchar(16))") # 执行insert语句 cursor.execute("insert into studnet values(1,'yang'),(2,'lang')") # 执行select语句,返回的结果是影响的记录数 result = cursor.execute("select * from studnet") print(result) # 输出 2 print(cursor.fetchall()) # 输出 ((1, 'yang'), (2, 'lang')) conn.commit() conn.close()
1.15.3 避免sql注入
-
避免sql注入
name = input("请输入用户名:") password = input("请输入密码:") # 执行sql语句 # 当name值以 "# 结尾时,就会发生sql注入的风险F cursor.execute(f'select * from user \ where name="{name}" and password="{password}"') # 避免sql注入 sql = 'select * from user where name=%s and password=%s' cursor.execute(sql, (name, password))
1.15.4 sqlalchemy
-
sqlalchemy操作数据库
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, create_engine from sqlalchemy.orm import sessionmaker Base = declarative_base() class User(Base): __tablename__ = "user" id = Column(Integer, primary_key=True) name = Column(String) password = Column(String) def __repr__(self): return f"id={self.id},name={self.name},password={self.password}" # 链接数据库 conn_info = "mysql+pymysql://root:123456@127.0.0.1:3306/text" engine = create_engine(conn_info, encoding="utf8") # 使用连接引擎创建一个session session = sessionmaker(bind=engine)() # 添加数据 s1 = User(id=1, name="yang", password="123456") session.add(s1) s2 = User(id=2, name="lang", password="456123") s3 = User(id=3, name="ssun", password="741258") session.add_all([s2, s3]) # 删除数据 user_1 = session.query(User).filter_by(id=3).first() session.delete(user_1) # 更新数据 session.query(User).filter_by(id=2).update({"name":"ssun"}) # 查询数据 print(session.query(User).all()) print(session.query(User).filter_by(name="ssun").first()) session.commit()
F