Python基础+进阶(万字总结,基础案例+执行结果)
2021/11/21 12:09:50
本文主要是介绍Python基础+进阶(万字总结,基础案例+执行结果),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Python基础篇
第一章:基础语法
输出相关:
- 基本输出案例
print("HelloWorld") # 执行结果: ''' HelloWorld '''
- 转义字符
# 转义字符"/" # 输出前加"r",输出原始字符串,即去除转义字符 # 输出前加"f",输出填补字符串,和format相似 name = 'c:\\user' x = '路径c:\\user' y = r"路径c:\user" z = f"路径{name}" print(x,"\n",y,"\n",z) # 执行结果: ''' 路径c:\user 路径c:\user 路径c:\user '''
- 占位符
age = 17 print("我的年龄是:%d岁"%age) # 执行结果: ''' 我的年龄是:17岁 '''
- 间隔符
print("www", "baidu", "com", sep = ".") # 执行结果: ''' www.baidu.com '''
- 控制符
print("hello", end = "") print("world") # 执行结果: ''' helloworld '''
- 连接符
name = "World" print("Hello" + name) # 执行结果: ''' HelloWorld '''
- 复制符
count = "num " print(count*3) # 执行结果: ''' num num num '''
- 进制转换
x = 100 print(bin(x)) #转换为二进制 print(oct(x)) #转换为八进制 print(hex(x)) #转换为16进制 # 执行结果: ''' 0b1100100 0o144 0x64 '''
- 去除/替换指定字符
a = "abcd" print(a.strip("dc")) print(a.replace('ab','-')) # 执行结果: ''' ab -cd '''
- 切割字符串
a = "ab_cd" # rsplit()从右开始切 # lsplit()从左开始切 print(a.split("_")[0]) print(a.split("_")[1]) # 执行结果: ''' ab cd '''
- format
x = "我是{name},今年{age}".format(name = 'cjl', age = 18) print(x) # 执行结果: ''' 我是cjl,今年18 '''
输入相关:
- 基础输入案例
password = input("请输入密码:") print("你输入的密码是:", password) print(type(password)) # 执行结果: ''' 请输入密码:666 你输入的密码是: 666 <class 'str'> '''
input
默认输入后的类型为字符串- 输入后类型强转
password = int(input("请输入密码:")) print("你输入的密码是:", password) print(type(password)) # 执行结果: ''' 请输入密码:666 你输入的密码是: 666 <class 'int'> '''
运算符相关:
算法运算符
+
加法-
减法*
乘法/
除法%
取模**
指数//
整除
比较运算符
<
小于>
大于<=
小等>=
大等==
恒等!=
不等
身份运算符
is
判断两个变量引用对象是否相同is not
判断两个变量引用对象是否不同- 用来检测两个变量是否是同一个变量
成员运算符
in
包含not in
不包含- 用来检测某成员是否是另一个变量的成员
逻辑运算符
not
逻辑非,都为假时运行or
逻辑或,一个为真时就运行and
逻辑与,都为真才运行- and看做乘法,or看做加法
- Ture看做1,False看做0
赋值运算符
+=
:x += 1
==x + 1=
-=
:x -= 1
==x - 1=
*=
:x *= 1
==x * 1=
/=
:x /= 1
==x / 1=
%=
:x %= 1
==x % 1=
//=
:x //= 1
==x // 1=
**=
:x **= 1
==x ** 1=
运算符规则
- 数值运算可能改变结果的数据类型,类型的改变与运算符有关,有如下基本规则:
整数
和浮点数
混合运算,输出结果是浮点数
整数
之间运算,产生结果类型与操作符相关,除法
运算的结果是浮点数
整数
或浮点数
与复数
运算,输出结果是复数
第二章:判断和循环
if条件判断:
- if基本格式
if 条件1: 内容 elif 条件2: 内容 else: 内容
- 嵌套if格式
if 条件1: if 条件2: if 条件3: 内容 else: 内容 else: else:
- 一行式双分支(又叫三元表达式)
age = int(input("输入年龄:")) print("未成年" if age<18 else "成年了") ''' #执行结果: 输入年龄:18 成年了 '''
- if判断案例-石头剪刀布
import random print("{0}石头剪刀布游戏{1}".format("*"*10, "*"*10)) print("[0代表:石头]", "[1代表:剪刀]", "[2代表:布]", sep = '\n') game = ["石头", "剪刀", "布"] num = input("请输入石头、剪刀、布(0、1、2):") robot = random.randint(0, 2) if num.isdigit() and int(num) >= 0 and int(num) <= 2: num = int(num) print("你出的是'%s',"%game[num], end="") if (num == 0 and robot == 1) or (num == 1 and robot == 2) or (num == 2 and robot == 0): print("而电脑出的是'%s' — 你赢了!"%game[robot]) elif num == robot: print("而电脑出的也是'%s' — 平局!"%game[robot]) else: print("而电脑出的是'%s' — 你输了!"%game[robot]) else: print("<输入有误!>") # 执行结果: ''' **********石头剪刀布游戏********** [0代表:石头] [1代表:剪刀] [2代表:布] 请输入石头、剪刀、布(0、1、2):2 你出的是'布',而电脑出的也是'布' — 平局! '''
for循环:
- for基本格式
for 表达式1 in 表达式2: 内容
- 嵌套for格式
for 表达式1 in 表达式2: for 表达式1 in 表达式2: 内容
- for循环案例-九九乘法表
for i in range(1, 10): for j in range(1, i+1): print("%d*%d=%d"%(i, j, i*j), end="\t") print("\n") # 执行结果: ''' 略······ '''
- 一行式九九乘法表
print('\n'.join([' '.join(['%d*%d=%-2d'%(y,x,x*y) for y in range(1,x+1)]) for x in range(1,10)]))
- for循环案例-打印菱形
for i in range(1, 6, 2): print(('*' * i).center(5)) for i in reversed(range(1, 4, 2)): print(('*' * i).center(5)) # 执行结果: ''' * *** ***** *** * '''
while循环:
- while基本格式
while 条件: 内容 表达式
- while实例:
i = 1 sum = 0 while i<=100: sum = sum + i i += 1 print(sum) # 执行结果: ''' 5050 '''
- while-else格式
while 条件: 内容 表达式 else: 内容
- while-else实例:
num = 0 while num < 3: print("num小于3") num += 1 else: print("num等于或大于3") # 执行结果: ''' num小于3 num小于3 num小于3 num等于或大于3 '''
循环扩展:
- break - 结束整个循环体
- continue - 结束本次循环
第三章:数据类型
字符串相关:
- 切片
str = "abcde12345" print(str) print(str[0]) print(str[0:5]) print(str[0:5:2]) #str[起始:结尾:步长] # 执行结果: ''' abcde12345 a abcde ace '''
list(列表):
list
基本格式
# 列表名 = [" "," "," "] nums = ["a",1,"b"]
- 遍历列表
names = ["李华", "小明", "马瑞"] for name in names: print(name) # 执行结果: ''' 李华 小明 马瑞 '''
- 增
a = [1,2] b = [3,4] #******append****** a.append(b) #将列表b内的每个元素,看做一个整体追加在列表a的最后面 print(a) #******extend****** a.extend(b) #将列表b内的每个元素,拆分开逐一追加在列表a的最后面 print(a) #******insert****** a.insert(1,5) #将元素5插入到列表a元素下标为1的位置 print(a) #执行结果: ''' [1, 2, [3, 4]] [1, 2, [3, 4], 3, 4] [1, 5, 2, [3, 4], 3, 4] '''
- 删
nums = ["a","b","c",1,2,3] #******del****** del nums[2] #删除列表nums下标为2的元素 print(nums) #******pop****** nums.pop() #删除列表nums最后一个元素 print(nums) #******remove****** nums.remove("b") #删除指定内容的元素 print(nums) #执行结果: ''' ['a', 'b', 1, 2, 3] ['a', 'b', 1, 2] ['a', 1, 2] '''
- 改
names = ["张三","李四"] print(names) names[0] = "小三" print(names) #执行结果: ''' ['张三', '李四'] ['小三', '李四'] '''
- 查
names = ["张三","李四","张三"] name = input("请输入要查的元素:") if name in names: #index查询的元素有多个时,则输出第一个元素的下标 print("该元素存在,该元素的下标为:%d"%names.index(name)) else: print("该元素不存在") #count查询该元素在列表中出现的次数 print("该列表存在 %d 个%s"%(names.count(name),names[names.index(name)])) #执行结果: ''' 请输入要查的元素:张三 该元素存在,该元素的下标为:0 该列表存在 2 个张三 '''
- 列表生成式:
# 一般写法: l = ['a_666','b_666','c_666',"d"] new_l1 = [] for i in l: if i.endswith('666'): new_l1.append(i) print(new_l1) # 生成式写法: new_l2 = [i for i in l if i.endswith('666')] print(type(new_l2), new_l2) #执行结果: ''' ['a_666', 'b_666', 'c_666'] <class 'list'> ['a_666', 'b_666', 'c_666'] '''
- 列表排序:
- 内置排序函数:
-
nums = [1,2,3,6,5,4] print(nums) #******reverse****** nums.reverse() #逆序 print(nums) #******sort****** nums.sort() #升序 print(nums) nums.sort(reverse=True) #降序 print(nums) #执行结果: ''' [1, 2, 3, 6, 5, 4] [4, 5, 6, 3, 2, 1] [1, 2, 3, 4, 5, 6] [6, 5, 4, 3, 2, 1] '''
- 冒泡排序:
-
def bubbleSort(alist): n = len(alist) for i in range(n): for j in range(0, n-i-1): if alist[j] > alist[j+1] : alist[j], alist[j+1] = alist[j+1], alist[j] alist = [64, 34, 25, 12, 22, 11, 90] print ("排序前的数组:", alist) bubbleSort(alist) print ("排序后的数组:", alist) # 执行结果: ''' 排序前的数组: [64, 34, 25, 12, 22, 11, 90] 排序后的数组: [11, 12, 22, 25, 34, 64, 90] '''
- 插入排序:
-
def insertSort(alist): n = len(alist) for i in range(1,n): while i > 0: if alist[i] < alist[i-1]: alist[i], alist[i-1] = alist[i-1], alist[i] i -=1 else: break alist = [64, 34, 25, 12, 22, 11, 90] print ("排序前的数组:", alist) insertSort(alist) print ("排序后的数组:", alist) # 执行结果: ''' 排序前的数组: [64, 34, 25, 12, 22, 11, 90] 排序后的数组: [11, 12, 22, 25, 34, 64, 90] '''
- 枚举
nums = ["a","b","c","d"] for i,j in enumerate(nums): print(i,j) #执行结果: ''' 0 a 1 b 2 c 3 d '''
- 嵌套列表(二位数组)基本格式
列表名 = [["",""],["",""],["",""]] print(列表名[外列表下标][内列表下表])
list列表
实例
products = [["redmi k30",1499],\ ["redmi k30 pro",2699],\ ["redmi k30 pro变焦版",2999],\ ["redmi k30至尊纪念版",1999],\ ["redmi k30S至尊纪念版",2599],\ ["手机壳",20],\ ["钢化膜",10],\ ["OTG",8]] print("\n------商品列表------") #遍历商品列表和价格 for x,phones in enumerate(products): print(x+1,"%-20s"%phones[0],"%d元"%phones[1]) print("\n------选购环节------") #用户自行选购 shopping_cart = [] num = input("请输入需要添加进购物车商品的编号:") while num != "exit": if num.isdigit() and int(num)>0 and int(num)<=len(products): shopping_cart.append(products[int(num)-1]) print("请问还需添加其他商品到购物车吗?") print("若需添加请输入对应编号,结账请输入:exit") num = input("请输入需要添加进购物车商品的编号:") else: num = input("该商品不存在,请重新输入:") else: print("\n------结账环节------") money = 0 if len(shopping_cart) != 0: print("以下是您购物车内的商品:") for shopping in shopping_cart: print(shopping[0],":%d元"%shopping[1]) money = money + shopping[1] print("您本次共需支付:%d元"%money) else: print("购物车空空如也。") print("******感谢您的光临,下次再见~******") #执行结果: ''' ------商品列表------ 1 redmi k30 1499元 2 redmi k30 pro 2699元 3 redmi k30 pro变焦版 2999元 4 redmi k30至尊纪念版 1999元 5 redmi k30S至尊纪念版 2599元 6 手机壳 20元 7 钢化膜 10元 8 OTG 8元 ------选购环节------ 请输入需要添加进购物车商品的编号:5 请问还需添加其他商品到购物车吗? 若需添加请输入对应编号,结账请输入:exit 请输入需要添加进购物车商品的编号:7 请问还需添加其他商品到购物车吗? 若需添加请输入对应编号,结账请输入:exit 请输入需要添加进购物车商品的编号:exit ------结账环节------ 以下是您购物车内的商品: redmi k30S至尊纪念版 :2599元 钢化膜 :10元 您本次共需支付:2609元 ******感谢您的光临,下次再见~******
tuple(元组):
tuple
基本格式
#元组名 = (" "," "," ") tup = (123,) #单个元素时结尾加逗号 tup = (1,2,3)
- 遍历元组
- 和
list列表
操作相同
- 和
- 增删改查
- 增:只能通过
连接
2个不同的元祖生成一个新元组 - 删:只能通过
del 元组名
删除整个元组 - 改:元组元素不支持修改
- 查:和
list列表
操作相同
- 增:只能通过
dict(字典):
dict
基本格式
#字典名 = {"":"", "":""} peoples = {"张三":18, "李四":15} #创建空字典 person = dict()
- 遍历字典
peoples = {"张三":18, "李四":15} for key,value in peoples.items(): print(key,value) #执行结果: ''' 张三 18 李四 15 '''
- 增
peoples = {"张三":18, "李四":15} age = input("请输入年龄:") peoples["王五"] = age print(peoples) #执行结果: ''' 请输入年龄:17 {'张三': 18, '李四': 15, '王五': '17'} '''
- 删
peoples = {"张三":18, "李四":15, "王五":17} del peoples["张三"] #删除指定的键值对 peoples.pop("李四") #和del作用相同 print(peoples) peoples.clear() #清空字典内的内容 print(peoples) del peoples #删除整个字典,删除后不可访问 #执行结果: ''' {'王五': 17} {} '''
- 改
peoples = {"张三":18, "李四":15} peoples["张三"] = 17 print(peoples) #执行结果: ''' {'张三': 17, '李四': 15} '''
- 查
peoples = {"张三":18, "李四":15} #******keys****** print(peoples.keys()) #得到所有键 #******values****** print(peoples.values()) #得到所有值 #******items****** print(peoples.items()) #得到所有键值对 #******get****** print(peoples.get("小三","该键不存在")) #查找指定键对应的值 #执行结果: ''' dict_keys(['张三', '李四']) dict_values([18, 15]) dict_items([('张三', 18), ('李四', 15)]) 该键不存在 '''
- 其他操作
- 合并两个字典:
dict1.update(dict2)
- 把两个列表转换为字典:
dict(zip(list1,list2))
- 合并两个字典:
- 字典生成式
keys = [('name','cjl'),('age',18),('sex','男')] dic = {k:v for k,v in keys if k != 'sex'} print(type(dic), dic) #执行结果: ''' <class 'dict'> {'name': 'cjl', 'age': 18} '''
set(集合):
set
基本格式
#集合名 = {"", "", ""} nums = {"a", 1, "b", 2}
set
独有操作
s = {1010, "张三", 78, 9} t = {1010, "李四", 12.3, 1010} print(s - t) # 差集 print(s & t) # 交集 print(s ^ t) # 补集 print(s | t) # 并集 #执行结果 ''' {'张三', 9, 78} {1010} {'张三', 9, '李四', 12.3, 78} {1010, '张三', 9, '李四', 12.3, 78} '''
- 集合类型的常用操作函数或方法
s = {1010, "python", 78.9} print("初始元组为:",s) # s.add(x):如果数据项x不在集合s中,将x增加到s s.add('大数据') print("添加后:",s) s.remove(1010) # s.remove(x):如果x在集合s中,移除该元素;元素不存在则产生KeyError异常 print("删除后:",s) s.clear() # s.clear():移除s中所有数据项 print("清空后:",s) print("元素个数:",len(s)) # len(s):返回集合s元素个数 print("1010是s元组内:",1010 in s) # x in s:如果x是s的元素,返回True,否则返回False print("1010不是s元组内:",1010 not in s) # x not in s:如果x不是s的元素,返回True, 否则返回False print("输出元组s:",s) #执行结果: ''' 初始元组为: {'python', 1010, 78.9} 添加后: {'python', 1010, '大数据', 78.9} 删除后: {'python', '大数据', 78.9} 清空后: set() 元素个数: 0 1010是s元组内: False 1010不是s元组内: True 输出元组s: set() '''
set()
函数将其他的组合数据类型变成集合类型,返回结果是一个无重复且排序任意
的集合,set()
函数也可以生成空集合
变量。
a = set() print(a) s = set("知之为知之不知为不知") print(s) #执行结果: ''' set() {'之', '知', '为', '不'} '''
- 集合生成式
keys = ['name','age','sex'] set_1 = {key for key in keys} print(type(set_1), set_1) #执行结果: ''' <class 'set'> {'name', 'age', 'sex'} '''
小结对比:
NULL | 是否有序 | 是否可变类型 |
---|---|---|
列表["",""] | 有序 | 可变类型 |
元祖("","") | 有序 | 不可变类型 |
字典{"":""} | 无序 | 键不可变,值可变 |
集合{"",""} | 无序 | 可变类型(不重复) |
第四章:函数
函数的定义和调用:
- 定义函数格式
#def 函数名(形参): # 内容 def Num(a,b): return a+b print(Num(5,10)) #执行结果: ''' 15 '''
函数的参数:
- 必选参数
def sum(a,b): sum = a+b print(sum) sum(333,333) #执行结果: ''' 666 '''
- 缺省参数
def sum(a=333,b=111): sum = a+b print(sum) sum(b=333) #执行结果: ''' 666 '''
- 可选参数
传入的参数列表为
元祖
def sumCount(*args): result = 0 for item in args: result += item print(result) sumCount(111,222,333) #执行结果: ''' 666 '''
- 关键字参数
传入的参数列表为
字典
def demo(**dict): print(dict) pass demo(name='cjl', age=18) #执行结果: ''' {'name': 'cjl', 'age': 18} '''
- 参数相关案例
def people(name, age=18, *phone, **contact): print("我是{0},今年{1}岁".format(name,age)) print("我的手机号是:{0}".format(phone)) print("我的其他联系方式:%s"%contact) people("cjl","19",12345,54321,qq="2653644677",wechat="chen2653644677") #执行结果: ''' 我是cjl,今年19岁 我的手机号是:(12345, 54321) 我的其他联系方式:{'qq': '2653644677', 'wechat': 'chen2653644677'} '''
参数的引用:
- 在python当中万物皆对象,在函数调用的时候,实参传递的就是对象的引用
- 了解了原理之后,就可以更好的去把控在函数内部的处理是否会影响到函数外部的数据变化
- 参数传递是通过对象引用来完成的
li=[] def test(parms): li.append([1,2,3]) print(id(parms)) print("内部的{}".format(parms)) print(id(li)) test(li) print("外部的{}".format(li)) #执行结果: ''' 2712787529992 2712787529992 内部的[[1, 2, 3]] 外部的[[1, 2, 3]] '''
函数返回值:
- return
def fun(a,b): sum = a + b return sum, sum * a rs1,rs2 = fun(10,10) print('rs1={0},rs2={1}'.format(rs1,rs2)) #执行结果: ''' rs1=20,rs2=200 '''
函数的嵌套:
- 从上向下执行
def fun1(): print("111") def fun2(): print("*****") fun1() def fun3(): print("333") fun3() print("*****") fun2() #执行结果: ''' ***** 111 333 ***** '''
变量作用域:
- 局部变量
def text1(): a = 123 print("修改前:%d"%a) a = 666 print("修改后:%d"%a) def text2(): a = 888 print("text2的a值和text1中的a值不冲突--%d"%a) text1() text2() #执行结果: ''' 修改前:123 修改后:666 text2的a值和text1中的a值不冲突--888 '''
- 全局变量
a = 666 #全局变量 def text1(): print(a) #调用全局变量a def text2(): print(a) #调用全局变量a text1() text2() #执行结果: ''' 666 666 '''
- 局部、全局变量名相同时
a = 100 #全局变量a def text1(): a = 123 #局部变量a和全局变量同名时,局部优先 print("修改前:%d"%a) a = 666 print("修改后:%d"%a) def text2(): print("a的值为:%d"%a) #没有局部变量,默认调用全局变量 def text3(): global a #声明全局变量在函数中的标识符 a = 200 print("使用global修改全局变量后:%d"%a) text1() text2() text3() #执行结果: ''' 修改前:123 修改后:666 a的值为:100 使用global修改全局变量后:200 '''
匿名函数:
- 既然叫
匿名
函数,所以该函数定义时就不需要定义函数名 - 和一般函数的区别:匿名函数仅用于临时调用一次,调用完就被回收
- 常用于调用其他函数时,
嵌套在其他函数内使用
- lambda表达式
a = 6 b = 10 # 方式一(违背了`匿名`原则): rs1 = lambda x,y:max(x,y) print(rs1(a,b)) # 方式二(其他函数被lambda被动调用): rs2 = (lambda x,y:max(x,y))(a,b) print(rs2) # 方式三(推荐使用): dic = { "ls": 175, "zt": 178, "zc": 175, "cjl": 184 } def func(k): return dic[k] res = max(dic, key=func) print(res) #执行结果: ''' 10 10 cjl '''
递归函数:
- 递归的本质就是循环,函数自己调用自己,默认递归上限1000次
- 没有尾递归优化
- 递归的两个阶段
- 回溯:
- 一层一层调用下去
- 递推:
- 满足某种结束条件,结束递归调用,然后一层一层返回
- 回溯:
# 理由递归计算阶乘 def digui(n): if n == 1: return 1 else: return n*digui(n-1) print(digui(5)) #执行结果: ''' 120 '''
- 递归的应用:
# 取出列表内的值 l = [1,2,[3,[4,[5,[6,[7,[8,[9,[10]]]]]]]]] def fun(list1): for x in list1: if type(x) is list: fun(x) else: print(x,end=' ') fun(l) #执行结果: ''' 1 2 3 4 5 6 7 8 9 10 '''
- 递归二分法搜索
nums = [1,2,15,-5,-56,-26,-2,54,62,56,66,99] def binary_search(find_num, nums): print(nums) if len(nums) == 0: print("要找的值不存在") return cen_num = len(nums) // 2 if find_num > nums[cen_num]: nums = nums[cen_num+1:] binary_search(find_num, nums) elif find_num < nums[cen_num]: nums = nums[:cen_num] binary_search(find_num, nums) else: print("找到了") find_num = int(input("请输入要查的数字:")) nums.sort() binary_search(find_num, nums) # 执行结果: ''' 请输入要查的数字:-2 [-56, -26, -5, -2, 1, 2, 15, 54, 56, 62, 66, 99] [-56, -26, -5, -2, 1, 2] 找到了 '''
内置函数:
max(x)
:获取最大值- 一般比较用法:
max(列表)
- 比较字典的值,获取
最大值
对应的键 -
dic = { "ls": 175, "zt": 178, "zc": 175, "cjl": 184 } res = max(dic, key=lambda k:dic[k]) print("最大值对应的键为:" + res) # 最大值对应的键为:cjl
- 一般比较用法:
min(x)
:获取最小值- 一般比较用法:
min(列表)
- 比较字典的值,获取
最小值
对应的键,和获取最大值用法相同
- 一般比较用法:
cmp(a,b)
- 用于判断a和b的大小关系,
a<b返回-1
,a==b返回0
,a>b返回1
- 用于判断a和b的大小关系,
eval('')
- 用来执行一个字符串表达式,并返回表达式的值
-
a,b = 10, 6 print(eval('a*b + pow(b,2) - 66')) print(int('3.14'), eval('3.14')) # 30 # 3 3.14
all(xxx)
- 如果参数列表中含有
False、0
则返回False
,否则返回True
-
li=[0,1,2] print(all(li)) # False
- 如果参数列表中含有
any(xxx)
- 如果参数列表都为
False、空、0
则返回False
,否则返回True
-
li=[0,1,2] print(any(li)) # True
- 如果参数列表都为
xxx.sort()
- 仅对
list列表
进行排序操作,直接修改原始对象,默认为升序 - 参数:
key=len
:按字符串长度排序key=str.lower
:忽略大小写排序reverse=True
:更改为降序
- 仅对
sorted(xxx)
- 对
所有
可迭代的对象进行排序操作,不改变原来的对象,而是返回一个新的列表,参数reverse=True
时排序顺序为降序 -
dic = { "ls": 175, "zt": 178, "zc": 175, "cjl": 184 } res = sorted(dic, key=lambda k:dic[k]) print(res) # ['ls', 'zc', 'zt', 'cjl']
- 对
zip(xx,xx,...)
- 把序列中对应的索引位置的元素,储存为一个元祖,可强转为list列表输出
-
li=['a','b','c'] ls=['我','你','他'] print(list(zip(li,ls))) # [('a', '我'), ('b', '你'), ('c', '他')]
enumerate()
- 返回一个枚举对象,用于将一个可遍历的数据对象(如:列表、元祖、字符串)组合为一个索引序列
-
li=['你','真','菜'] for item in enumerate(li,1): print(item,end=' ') # (1, '你') (2, '真') (3, '菜')
hasattr(x,x)
- 用于判断对象是否包含对应的属性
-
class hasattrDemo: a = 1 demo = hasattrDemo() print(hasattr(demo,'a'),hasattr(demo,'b')) # True False
isinstance(a,b)
- 用于判断a是否是b类型,类似于type()
vars()
- 用于返回对象的属性和属性值的字典对象
map()
(了解)- 据提供的函数对指定序列做映射
-
l = [1,2,3,4,5] def square(x): return x ** 2 res = list(map(square, l)) print(res) # 使用lambda匿名函数 # print(list(map(lambda x: x ** 2, l))) # 执行结果: ''' [1, 4, 9, 16, 25] '''
- 对字典
-
L = ["1","2","3","4","5"] def func(key): dic = {"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6} return dic[key] res = list(map(func, L)) print(res) # 执行结果: ''' [1, 2, 3, 4, 5] '''
reduce()
(了解)- 对参数序列中元素进行累积
-
from functools import reduce L = [1,2,3,4,5] def func(x,y): return x*10 + y res = reduce(func,L) print(type(res), res) # 执行结果: ''' <class 'int'> 12345 '''
iter()
:返回一个迭代器next()
:获取迭代器中下一个元素-
lis = [i for i in range(1,3)] print(lis) ite = iter(lis) print(ite) print(next(ite)) print(next(ite)) #执行结果: [1, 2] <list_iterator object at 0x000002515BCE5370> 1 2
第五章:面向对象(上)
类和对象:
- 需用class关键字
- 类命名
- 遵循“大驼峰”
- 首字母大写
#定义一个类 class Student(): #定义空类时,可用pass当做占位符 pass #定义类中的函数一般需用self站位(self可替换),例如: class StudentAll(): name = 'cjl' age = 18 language = 'python' def hello(self): print("你好!") student = StudentAll() student.hello() print(student.name, student.age, student.language) #执行结果: ''' 你好! cjl 18 python '''
self:
self
在对象的方法中表示当前对象本身,如果通过对象调用一个方法,那么该对象会自动传入到当前方法的第一个参数中self
并不是关键字,只是一个用于接受对象的普通参数,理论上可以用任何一个普通变量名代替- 方法中有
self形参
的方法成为非绑定类的方法,可以通过对象访问,没有self的是绑定类的方法,只能通过类访问 - 使用类访问绑定类的方法时,如果类方法中需要访问当前类的成员,可以通过
__class__
成员名 self
指的是类实例对象本身,相当于java的this
class Teacher(): name = "cjl" age = 18 def say(self): self.name = "aaa" self.age = "19" print("my name is {}".format(self.name)) #调用类内的成员时需要使用__class__ print("my age is {}".format(__class__.age)) def sayAgain(): print(__class__.name) print(__class__.age) print("hello") t = Teacher() t.say() #调用绑定类函数使用类名 Teacher.sayAgain() #执行结果: ''' my name is aaa my age is 18 cjl 18 hello '''
五种下划线:
_
:用于临时或无意义变量的名称_xxx
:命名约定,说明该属性或方法仅供内部使用,但解释器不会强制执行xxx_
:避免声明的变量和关键字冲突__xxx
:用于声明属性和方法的私有化,解释权强制执行__xxx__
:Python自带的魔术方法,应避免自己声明该命名方式
__init__构造函数:
- python自带的内置函数具有特殊的函数,使用双下划线包起来的【魔术方法】
- 是一个初始化的方法用来定义实例属性和初始化数据的,在创建对象的时候
自动调用,不用手动去调用
- 利用传参的机制可以让我们定义功能更加强大并且方便的类
class People(): def __init__(self,name,age): self.name = name self.age = age cjl = People('陈家霖',18) print('我是{0}今年{1}岁'.format(cjl.name, cjl.age)) #执行结果: ''' 我是陈家霖今年18岁 '''
魔术方法:
__name__
:输出当前的类名
if __name__ == '__main__': ...
__all__
:在使用from xxx import *
导入模块时,不会导入__all__=[]
外的方法,但import xxx
不受影响__str__
:在将对象转换成字符串,相当于java的toString
class People(): def __init__(self,name,age): self.name = name self.age = age def __str__(self): return '我是{0}今年{1}岁'.format(self.name, self.age) cjl = People('陈家霖',18) print(cjl) #执行结果: ''' 我是陈家霖今年18岁 '''
__new__
:优先__init__
初始化方法被调用,第一个参数默认为cls
class Person(object): def __init__(self, name, age): print('执行__init__') self.name = name self.age = age def __new__(cls, name, age): print('执行__new__') return super(Person, cls).__new__(cls) def __str__(self): return '<Person: %s(%s)>'%(self.name, self.age) cjl = Person('cjl', 18) print(cjl) #执行结果: ''' 执行__new__ 执行__init__ <Person: cjl(18)> '''
__mro__
:用于显示类的继承关系
class D(): def play(self): print("'D'类的play") class C(D): def play(self): print("'C'类的play") class B(D): pass class A(B,C): pass demo = A() demo.play() print(A.__mro__) #执行结果: ''' 'D'类的play (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.D'>, <class 'object'>) '''
__dict__
:用于查看类的所有属性,以字典形式显示
class People(): def __init__(self,name,age): self.name = name self.age = age cjl = People('cjl',18) print(cjl.__dict__) #执行结果: ''' {'name': 'cjl', 'age': 18} '''
析构方法:
__del__
:和__init__
一样自动执行,用于释放对象实现资源回收,当一个对象调用后,自动执行清理该对象;也可使用del 对象名
手动清理
class People(): def __init__(self,name): self.name = name print("我是 %s 执行构造方法"%name) def __del__(self): print("执行析构方法,回收对象") cjl = People("cjl") print("--------使用手动清理--------") del cjl # 手动清理 print(cjl) #执行结果: ''' 我是 cjl 执行构造方法 --------使用手动清理-------- 执行析构方法,回收对象 NameError: name 'cjl' is not defined '''
继承:
单继承
:一个子类继承一个父类(找亲爹)
class Person(): def __init__(self, name, age): self.name = name self.age = age def eat(self): print('吃饭...') class Men(Person): def __init__(self, name, age, height): super().__init__(name,age) self.height = height def play(self): print('玩儿...') def __str__(self): return '我是{}今年{}岁,身高{}'.format(self.name,self.age,self.height) cjl = Men('cjl',18,183) print(cjl, '\n调用父类方法:') cjl.eat() #执行结果: ''' 我是cjl今年18岁,身高183 调用父类方法: 吃饭... '''
多继承
:一个子类继承多个父类(认干爹)
class A(): def a(self): print("A:我是C类它祖先类") pass class B(A): def b(self): print("B:我是C类它父类") pass class C(B): pass num = C() num.a() num.b() print(C.__mro__) #执行结果: ''' A:我是C类它祖先类 B:我是C类它父类 (<class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>) '''
重写:
- 所谓重写,就是在子类中有一个和父类一模一样的方法,即子类的方法会覆盖父类的方法
class Dog(): def __init__(self,name,color): self.name = name self.color = color def bark(self): print("父类:汪汪汪的叫...") class HaShiQi(Dog): def __str__(self): return '这一只 {0} 的狗叫 {1} '.format(self.color,self.name) def bark(self): # 重写父类方法 print("子类:嗷嗷嗷的叫...") hsq = HaShiQi('哈士奇','白色') print(hsq) hsq.bark() #执行结果: ''' 这一只 白色 的狗叫 哈士奇 子类:嗷嗷嗷的叫... '''
多态:
- 多态的实现需要遵循两个条件:
- 继承、多态发生在父类和子类之间
- 重写、子类重写父类的方法
class Animals: def say_hello(self): print("我是一只小动物...") class People: def say_hello(self): print("我是人...") class Pig(Animals): def say_hello(self): print("我是可爱的小猪.") class Cat(Animals): def say_hello(self): print("我是呆萌的小猫.") class Dog(Animals): def say_hello(self): print("我是忠诚的小狗.") class Student(People): def say_hello(self): print("我是三年级的小朋友.") def commonInvoke(obj): obj.say_hello() listObj = [Pig(),Cat(),Dog(),Student()] for item in listObj: commonInvoke(item) #执行结果: ''' 我是可爱的小猪. 我是呆萌的小猫. 我是忠诚的小狗. 我是三年级的小朋友. '''
类属性和实例属性:
- 类属性是可以被类对象和实例对象共同访问使用的
- 实例属性只能由实例对象所访问
class Person: age = 18 def __init__(self,name): self.name = name cjl = Person('cjl') print(cjl.name) print(Person.name) #执行结果: ''' 实例对象: 18 cjl 类对象: 18 AttributeError: type object 'Person' has no attribute 'name' '''
类方法和静态方法:
- 类方法用
@classmethod
来修饰,类方法的第一个参数对象是cls
,虽然也能通过实例访问,但不推荐这样调用
class Person: people = 'cjl' @classmethod def get_name(cls): return cls.people @classmethod def change_name(cls,name): cls.people = name print('类方法调用:%s'%(Person.get_name())) p = Person() print('实例对象调用(不推荐):%s'%(p.get_name())) print('--------------修改之后----------------') Person.change_name('lxl') print(Person.get_name()) #执行结果: ''' 类方法调用:cjl 实例对象调用(不推荐):cjl --------------修改之后---------------- lxl '''
- 静态方法用
@staticmethod
来修饰,静态方法可以不带参数,使用类和实例均可调用
import time class TimeText: @staticmethod def time(): return time.strftime('%H:%M:%S',time.localtime()) print('类对象调用:',TimeText.time()) demo = TimeText() print('实例对象调用:',demo.time()) #执行结果: ''' 类对象调用: 09:44:47 实例对象调用: 09:44:47 '''
第六章:面向对象(下)
装饰器:
装饰器
就是在不修改不被装饰器对象源代码与调用方式的前提下为其添加新功能- 多个装饰器,则
由下往上
加载,由上到下
运行 - 无参装饰器模板:
# 无参装饰器基本模板 def outter(func): def wrapper(*args, **kwargs): # 1.调用原函数 # 2.为其添加新功能 res = func(*args,**kwargs) return res return wrapper
- 无参装饰器
语法糖
-> 使用@
修饰函数,例:
# @print -> home=print(home) @print def home(x,y): pass print(home)
- 实例:
def auth(func): def wrapper(*args, **kwargs): name = input("name>>>:") pwd = input("pws>>>:") if name == 'root' and pwd == '123': res = func(*args,**kwargs) return res else: print("输入错误") return wrapper @auth def index(): print("from index") index() #执行结果: ''' name>>>:root pws>>>:123 from index '''
- 带参装饰器模板:
def 有参装饰器(x,y,z): def outter(func): def wrapper(*args, **kwargs): res = func(*args, **kwargs) return res return wrapper return outter @有参装饰器(1,y=2,z=3) def 被装饰对象(): pass
- 实例:
# 只用套三层,第三层就可以无限接收参数了 def auth(db_type): def deco(func): def wrapper(*args, **kwargs): name = input('your name>>>: ').strip() pwd = input('your password>>>: ').strip() if db_type == 'file': print('基于文件的验证') if name == 'egon' and pwd == '123': res = func(*args, **kwargs) return res else: print('user or password error') elif db_type == 'mysql': print('基于mysql的验证') else: print('不支持该db_type') return wrapper return deco @auth(db_type='file') def index(x, y): print('index->>%s:%s' % (x, y)) @auth(db_type='mysql') def home(name): print('home->>%s' % name) # index(1, 2) # home('egon')
迭代器:
- 迭代指的是重复取值的过程,并且每次重复都是基于上一次的结果而继续的;而迭代器则是迭代取值的工具
- 可迭代对象:
- 只要内置有
__iter__()
方法的都称为可迭代对象字符串
,列表
,元组
,字典
,集合
,文件对象
- 调用可迭代对象下的
__iter__()
方法,会将其转换成迭代对象
- 只要内置有
- 迭代器对象:
- 内置有
__next__
方法并且内置有__iter__
方法的对象__next__()
: 得到迭代器的下一个值__iter__()
: 得到迭代器本身,
- 内置有
for循环
工作原理:for i in xxx
->for i in xxx.__iter__()
# while 遍历字典 key d = {'a':1, 'b':2, 'c':3} d_iterator = d.__iter__() while True: try: print(d_iterator.__next__()) except StopIteration: break # for 遍历字典 key for k in d: print(k)
- 迭代器优缺点:
- 优点:
- 为序列和非序列类型提供了一种统一的迭代取值方式
- 惰性取值;每次只取一个数据,不占内存;迭代器保存的是产生数据的算法,而不是实际的数据
- 缺点:
- 除非取尽,否则无法获取迭代器的长度
- 只能往后依次取值,不能返回头往前取值。就像象棋中的卒,只进不退
- 优点:
生成器:
- 用关键字
yield
为函数添加多个返回值,生成器
==迭代器
yield
-> 可以返回无数个值,并将函数挂起return
-> 只能返回一次值
def fun(): print("第一次") yield 1 print("第二次") yield 2 print("第三次") g = fun() g.__iter__() print(g.__next__()) print(g.__next__()) # 执行结果: ''' 第一次 1 第二次 2 '''
- 自定义迭代器
def my_range(start,stop,step=1): while start < stop: yield start start+=step for i in my_range(1,10,2): print(i,end=' ') # 执行结果: ''' 1 3 5 7 9 '''
yield
表达式:.send()
: 为yield传值,也可以传列表,但第一次传值必须是None
或next(x)
.close()
: 关闭后无法传值
def person(name): print("我是%s"%name) while True: x = yield print("%s是%s"%(name,x)) g = person("cjl") g.send(None) g.send("小菜B") g.close() g.send("大神") # 执行结果: ''' 我是cjl cjl是小菜B 报错... '''
私有化属性:
- 在属性前加
__
,私有化后在外部不能调用,子类不能继承
class Person: def __init__(self): self.__name = 'cjl' self.age = 18 def __str__(self): return '我是{0}今年{1}岁了'.format(self.__name, self.age) class Men(Person): def printInfo(self): # 无法继承父类的私有化属性 # print(self.name) print(self.age) p = Person() print(p) # 无法在外部访问私有化属性 # print(p.__name) men = Men() men.printInfo() #执行结果: ''' 我是cjl今年18岁了 子类继承父类: 18 '''
- 私有化方法:
- 和私有化属性一样,在方法前加
__
,私有化后在外部不能调用,子类不能继承
- 和私有化属性一样,在方法前加
property属性函数:
- 使用
property
属性函数,用于调用和修改私有化属性
class Person: def __init__(self): self.__age = 18 def get_age(self): return self.__age def set_age(self,age): if age < 0: print("年龄有误") else: self.__age = age age = property(get_age,set_age) cjl = Person() cjl.age = 19 print('修改后的年龄:',cjl.age) #执行结果: ''' 修改后的年龄: 19 '''
- 使用装饰器,用于调用和修改私有属性,用关键字
@property
和@xxx.setter
进行装饰,推荐使用该方法
class Person: def __init__(self): self.__age = 18 @property def age(self): return self.__age @age.setter def age(self,age): if age < 0: print("年龄有误") else: self.__age = age cjl = Person() cjl.age = 19 print('修改后的年龄:',cjl.age) #执行结果: ''' 修改后的年龄:19 '''
单例模式:
- 确保一个类只有一个实例的存在(类似win系统的回收站)
- 实现方式一:通过类属性保存初次创建的实例对象,如果存在就返回保存的,没有就创建新的实例对象
class DataBase(object): _instance = None def __init__(self, name, age): print(name, age) def __new__(cls, *args, **kwargs): if not cls._instance: cls._instance=super(DataBase,cls).__new__(cls) return cls._instance db1 = DataBase('cjl',18) print(id(db1)) db2 = DataBase('lxl',15) print(id(db2)) #执行结果: ''' cjl 18 2488840593520 lxl 15 2488840593520 '''
- 实现方式二:只执行一次init方法,通过类变量进行标记控制
class Demo(object): __instance = None __isinit = True def __init__(self, name, age): if Demo.__isinit: self.name = name self.age = age __isinit = False def __new__(cls, *args, **kwargs): if not cls.__instance: cls.__instance=super(Demo,cls).__new__(cls) return cls.__instance else: return cls.__instance d1 = Demo('cjl',18) print(id(d1), d1.name,d1.age) d2 = Demo('lxl',15) print(id(d2), d2.name,d2.age) #执行结果: ''' 2488816354400 cjl 18 2488816354400 lxl 15 '''
动态绑定属性方法:
- 动态添加类属性、方法属性
class People: def __init__(self,name,age): self.name = name self.age = age def __str__(self): return '{}今年{}岁了'.format(self.name,self.age) cjl = People('cjl',18) People.sex = '男' print(cjl) print("动态添加类属性:性别,",cjl.sex) #执行结果: ''' cjl今年18岁了 动态添加类属性:性别, 男 '''
- 动态绑定类方法
import types def textMothend(self): print('{}今年{}岁了,性别:{}'.format(self.name,self.age,self.sex)) @classmethod def classmethodTest(cls): print("类方法...") @staticmethod def staticmethodTest(): print("静态方法...") class People: def __init__(self,name,age): self.name = name self.age = age def __str__(self): return '{}今年{}岁了'.format(self.name,self.age) cjl = People('cjl',18) People.sex = '男' print(cjl) print("动态添加类属性:性别 -",cjl.sex) cjl.printInfo = types.MethodType(textMothend,cjl) #动态绑定方法 print("---------------动态绑定后-------------") cjl.printInfo() # 绑定类方法 People.TestMethod = classmethodTest print("通过类调用:",end='\t\t') People.TestMethod() print("通过实例对象调用:",end='\t') cjl.TestMethod() # 绑定静态方法 People.TestMethod = staticmethodTest print("通过类调用:",end='\t\t') People.TestMethod() print("通过实例对象调用:",end='\t') cjl.TestMethod() #执行结果: ''' cjl今年18岁了 动态添加类属性:性别 - 男 ---------------动态绑定后------------- cjl今年18岁了,性别:男 通过类调用: 类方法... 通过实例对象调用: 类方法... 通过类调用: 静态方法... 通过实例对象调用: 静态方法... '''
__slots__:
__slots__ = ()
:后跟元组,类型是字符串- 限制实例添加的属性,括号内为空时,则不允许添加任何属性;
- 节省空间,使用后则类属性不会被存放在
__dict__
内,所以无法使用__dict__
访问全部类属性; - 继承时
子类不受影响
,但如果子类也声明该方法时,则也会继承父类的属性限制
class Person(object): # 添加属性限制 __slots__ = ('name','age','sex') def __init__(self): pass def __str__(self): return '{}........{}'.format(self.name,self.age) class Men(Person): __slots__ = ('school') def __init__(self): pass def __str__(self): return '{}....{}....{}'.format(self.name,self.school,self.age) pass cjl = Person() cjl.name = 'cjl' cjl.age = 19 # cjl.school = 'sqxy' # 未在属性限制范围内,所以报错 print(cjl) cjl.sex = '男' lxl = Men() lxl.name = 'lxl' lxl.age = 15 lxl.school = '七中' print(lxl) #执行结果: ''' cjl........19 lxl....七中....15 '''
第七章:文件操作
读写文件:
- 常用访问模式:
r
:以只读方式打开(默认模式)w
:用于写入,如果文件存在会将其覆盖,不存在则会创建a
:用于写入,如果文件存在会在其后追加内容,不存在则会创建rb
:以二进制的只读方式打开wb
:以二进制的写入模式打开+
:打开一个文件进行更新(可读可写)- 注: 路径中由于
\
是转义符,所以表示路径时,使用\\
或/
或路径前加r
encoding='utf-8'
设置文件编码,二进制读写时不用设置编码- 基本格式:
#变量名 = open("文件名","访问模式") #文件名.close() txt = open(r'路径', 'r', encoding='utf-8') print(txt.read()) txt.close() # 推荐使用with格式,with格式: # with open("文件名",'访问模式') as 别名: with open(r'路径', 'r') as txt: print(txt.read())
- 文件读取生成式:
# 生成式读取文件字节 with open('test.txt', 'rb') as r: # 生成式 res = sum(len(line) for line in r) print(res) #执行结果: ''' 38889
- 文件读写相关方法:
.readline()
:从文件中读入一行内容.readlines()
:从文件中读入所有行,以每行为元素形成一个列表.write()
:单行写入,将一个字符串写入文件.writelines()
:直接将列表类型的各元素连接起来并写入.tell()
:文件定位,获取当前文件指针读取到的位置.truncate(x)
:截取输出前x个字符.seek(x,y)
:改变当前文件操作指针的位置,x的值为偏移量单位字节,y的值(0: 文件开头; 1: 当前位置; 2: 文件结尾)
- 文件操作实例:
# 文件的读写 - 文件备份 def run(name): try: old_file = name new = old_file.split('.') new_file = new[0] + '_备份.' + new[1] with open(old_file,'rb') as r, open(new_file, 'wb') as w: for line in r: w.write(line) except Exception as result: print("输入的文件名不存在.") else: print(name, "文件备份完成.") name = input("请输入需要备份的文件名:") run(name) #执行结果: ''' 请输入需要备份的文件名:text.txt text.txt 文件备份完成. '''
- 实例2:
# .seek()的应用 - 监测文件的实时写入 import time with open('xxx', 'rb') as f: f.seek(0,2) while True: line = f.readline() if len(line) == 0: time.sleep(0.5) else: print(line.decode('utf8'))
遍历文件:
- 从文本文件中逐行读入内容并进行处理是一个基本的文件操作需求。文本文件可以看成是由行组成的组合类型,因此,可以使用遍历循环逐行遍历文件。
with open('路径', 'r') as txt: print(txt.readlines()) for x in txt: print(x)
操作文件:
- 文件重命名
import os os.rename("原名称", "新名称")
- 删除文件
import os os.remove("文件名")
- 获取当前目录
import os os.getcwd()
- 改变默认目录
import os os.chdir("路径")
- 遍历目录列表
import os with os.scandir('d:/') as scan: for s in scan: print(s.name)
- 遍历目录文件
import os basePath = 'd:/' for s in os.scandir(basePath): if os.path.isfile(os.path.join(basePath,s)) print(s)
- 创建文件夹
import os os.mkdir("文件夹名")
- 删除文件夹
import os os.redir("文件夹名")
第八章:错误与异常
常见的异常类型:
Exception
:代表所有异常类型AssertError
:断言语句(assert)失败AttributeError
:尝试访问未知的对象属性EOFError
:用户输入文件末尾标志EOF(Ctrl+d)FloatingPointError
:浮点计算错误GeneratorExit
:generator.close()方法被调用的时候ImportError
:导入模块失败的时候IndexError
:索引超出序列的范围KeyError
:字典中查找一个不存在的关键字KeyboardInterrupt
:用户输入中断键(Ctrl+c)MemoryError
:内存溢出(可通过删除对象释放内存)NameError
:尝试访问一个不存在的变量NotImplementedError
:尚未实现的方法oSError
:操作系统产生的异常(例如打开一个不存在的文件)OverflowError
:数值运算超出最大限制ReferenceError
:弱引用(weak reference)试图访问一个已经被垃圾回收机制回收了的对象RuntimeError
:一般的运行时错误StopIteration
:迭代器没有更多的值SyntaxError
:Python的语法错误IndentationError
:缩进错误TabError
:Tab和空格混合使用SystemError
:Python编译器系统错误SystemExit
:Python编译器进程被关闭TypeError
:不同类型间的无效操作UnboundLocalError
:访问一个未初始化的本地变量(NameError的子类)UnicodeError
:Unicode相关的错误(ValueError的子类)UnicodeEncodeError
:Unicode编码时的错误(UnicodeError的子类)UnicodeDecodeError
:Unicode解码时的错误(UnicodeError的子类)UnicodeTranslateError
:Unicode转换时的错误(UnicodeError的子类)ValueError
:传入无效的参数ZeroDivisionError
:除数为零
异常处理:
- 基本格式
''' try: 内容 except Exception as 别名: 内容 ''' try: print("----text--1----") f = open("不存在.txt","r") #该文件不存在,报错 print("----text--2----") except Exception as result: #Exception可以承接所有异常信息 print(result) #捕获异常后,执行的代码 #执行结果: ''' ----text--1---- [Errno 2] No such file or directory: '不存在.txt' '''
try...finally
嵌套,finally
内的代码无论有无异常都执行
import time try: f = open("test1.text","r") try: while True: content = f.readline() if len(content) == 0: break time.sleep(2) print(content) finally: f.close() print("文件关闭") except Exception as result: print("发生异常···") #执行结果: ''' 发生异常··· '''
手动引发异常:
- 使用
raise
关键字实现手动引发异常
try: print("我是cjl") #手动引发一个异常,注意语法:raise ErrorClassName raise ValueError print("还没完呀") except NameError as e: print("NameError") except ValueError as e: print ("ValueError") except Exception as e: print("有异常") finally: print("我肯定会被执行") #执行结果: ''' 我是cjl ValueError 我肯定会被执行 '''
自定义异常:
class TextException(Exception): def __init__(self,leng): self.len = leng def __str__(self): return '你输入的数据长度是:' + str(self.len) + ',超过长度了.' class TextDemo(): name = input('请输入数据:') try: if len(name) > 5: raise TextException(len(name)) else: print(name) except TextException as result: print(result) finally: print("执行完毕.") TextDemo() #执行结果: ''' 请输入数据:gfhsuidgoashuidghasu 你输入的数据长度是:20,超过长度了. 执行完毕. '''
Python进阶篇
第一章:进程、线程与协程
概述:
并发
:看上去一起执行,任务数大于CPU核心数并行
:一起执行,任务数必须小于等于CPU核心数同步
:指的是主动请求后等待I/O,数据就绪后读写必须阻塞异步
:指的是主动请求后,可处理其他任务,等I/O完毕后通知- 实现多任务的方式:
- 多进程方式
- 多线程方式
- 协程方式
- 多进程+多线程
多进程:
xxx = Process()
创建子进程,方法:target()
:子进程任务args()
:进程的说明(元组)xxx.start()
:启动子进程xxx.join()
:让父进程等待子进程结束之后父进程再结束,参数timeout=
父进程的等待时间(单位s)
from multiprocessing import Process import time import os def func(self): print("子进程---",os.getpid()) time.sleep(1.5) print("子进程结束...") if __name__ == '__main__': print("父进程启动...") p = Process(target=func, args=("python",)) p.start() p.join() print("父进程---",os.getpid()) print("父进程结束...") #执行结果: ''' 父进程启动... 子进程--- 8900 子进程结束... 父进程--- 20308 父进程结束... '''
- 在子进程中修改全局变量,对父进程中的全局变量没有影响
- 创建子进程的时候,其实是对全局变量做了一个备份
- 所有进程对全局变量的修改都不会影响其它进程
from multiprocessing import Process num = 100 def run1(): print("孙子进程开始...") global num num += 1 print("孙子进程num值: ", num) print("孙子进程结束...") def run(): print("子进程开始...") p1 = Process(target=run1) p1.start() p1.join() global num num += 1 print("子进程num值: ", num) print("子进程结束...") if __name__ == '__main__': print("父进程开始...") p = Process(target=run) p.start() p.join() print("父进程num值: ", num) print("父进程结束...") #执行结果: ''' 父进程开始... 子进程开始... 孙子进程开始... 孙子进程num值: 101 孙子进程结束... 子进程num值: 101 子进程结束... 父进程num值: 100 父进程结束... '''
- 多进程另一种调用方法 -> 继承进程类
from multiprocessing import Process class MyProcess(Process): # run()是固定的,当线程被执行的时候,被执行的就是run() def run(self): for i in range(100): print("子进程:", i) if __name__ == '__main__': t = MyProcess() # t.run() -> 调用该方法为单线程 t.start() # 启动子线程 for i in range(100): print("主进程", i)
进程池:
python
内置的进程池Pool
,导入from multiprocessing import Pool
模块,方法:pool.map(x,y)
:使进程阻塞直到返回结果(),参数x为方法,y为一个迭代器pool.apply()
: 同步执行(串行)(不建议使用)pool.apply_async()
: 异步执行(并行),非阻塞且支持结果返回进行回调pool.terminate()
: 立刻关闭进程池,不在处理未处理的任务pool.close()
: 等待所有进程结束后,才关闭进程池,使其不在接受新的任务pool.join()
: 主进程等待所有子进程执行完毕。必须在close()
或terminate()
之后。
from multiprocessing import Pool import time def task(i): time.sleep(1) print("任务%s执行结束..." % i) if __name__ == '__main__': # 实例化进程对象 pool = Pool(2) for i in range(1,6): pool.apply_async(func=task, args=(i, )) pool.close() pool.join() #执行结果: ''' 任务1执行结束... 任务2执行结束... 任务3执行结束... 任务4执行结束... 任务5执行结束... 任务6执行结束... '''
- 一次性开辟一些进程。我们用户直接给进程池子提交任务。进程任务的调度交给进程池来完成
from concurrent.futures import ProcessPoolExecutor def fun(name): for i in range(100): print(name,i) if __name__ == '__main__': # 创建进程池 with ProcessPoolExecutor(10) as t: for i in range(50): t.submit(fun, name=f'进程{i}') print("进程任务执行完毕...")
进程锁:
- 为了防止和多线程一样的出现数据抢夺和脏数据的问题,同样需要设置进程锁
from multiprocessing import Process from multiprocessing import Array from multiprocessing import RLock, Lock, Event, Condition, Semaphore import time def func(i,lis,lc): lc.acquire() lis[0] = lis[0] - 1 time.sleep(1) print('say hi', lis[0]) lc.release() if __name__ == "__main__": array = Array('i', 1) array[0] = 5 lock = RLock() for i in range(5): p = Process(target=func, args=(i, array, lock)) p.start() #执行结果: ''' say hi 4 say hi 3 say hi 2 say hi 1 say hi 0 '''
多线程:
- 线程的内存空间是共享的,每个线程都共享同一个进程的资源,但数据量大时容易引发数据混乱
xxx = threading.Thread()
创建子线程,方法:target()
:子线程任务args()
:线程的说明(元组)xxx.start()
:启动子线程xxx.join()
:让主线程等待子线程结束之后主线程再结束,参数timeout=
主线程的等待时间(单位s)
import threading,time def run(num): print("子线程%s开始..."%(threading.current_thread().name)) time.sleep(2) print(num) time.sleep(2) print("子线程%s结束..."%(threading.current_thread().name)) if __name__ == '__main__': print("主线程%s开始..."%(threading.current_thread().name)) # 创建子线程 t = threading.Thread(target=run,args=(1,),name='runThread') t.start() t.join() print("主线程%s结束..."%(threading.current_thread().name)) # 执行结果: ''' 主线程MainThread开始... 子线程runThread开始... 1 子线程runThread结束... 主线程MainThread结束... '''
- 多线程另一种调用方法 -> 继承线程类
from Thread import threading class MyThread(Thread): # run()是固定的,当线程被执行的时候,被执行的就是run() def run(self): for i in range(1000): print("子线程:", i) if __name__ == '__main__': t.MyThread() # t.run() -> 调用该方法为单线程 t.start() # 启动子线程 for i in range(1000): print("主线程", i)
线程锁:
xxx = threading.Lock()
创建互斥锁,用于避免数据混乱(一个线程执行完毕才开始执行下一个线程),但会影响多线程的并发执行,从而效率会大大降低lock.acquire()
: 加锁lock.release()
: 解锁with lock:
和文件操作相同,执行完自动解锁
import threading # 创建锁对象 lock = threading.Lock() num = 0 def run(n): global num for i in range(1000000): # 调用锁对象 with lock: num += n num -= n if __name__ == '__main__': t1 = threading.Thread(target=run,args=(6,)) t2 = threading.Thread(target=run,args=(9,)) t1.start() t2.start() t1.join() t2.join() print("num = ",num) # 执行结果: ''' num = 0 '''
生产者消费者模式:
- 先进先出的数据结构,即队列
import time,queue,threading q = queue.Queue(10) def product(i): while True: time.sleep(2) print("厨师%s 做了一个包子!" % i) q.put("厨师%s 做的包子!" % i) def consume(j): while True: time.sleep(1) print("顾客%s 吃了一个%s !" % (j, q.get())) for i in range(3): a = threading.Thread(target=product, args=(i, )) a.start() for j in range(10): b = threading.Thread(target=consume, args=(j, )) b.start()
信号量:
xxx = threading.Semaphore(x)
同时启用x个多线程同时执行
import threading,time # 创建2个多线程同时执行 sem = threading.Semaphore(2) def run(): with sem: print("%s--开始..."%(threading.current_thread().name)) time.sleep(1) print("%s--结束..." % (threading.current_thread().name)) if __name__ == '__main__': for i in range(5): t = threading.Thread(target=run) t.start() # 执行结果: ''' Thread-1--开始... Thread-2--开始... Thread-1--结束... Thread-2--结束... Thread-3--开始... Thread-4--开始... Thread-3--结束... Thread-4--结束... Thread-5--开始... Thread-5--结束... '''
线程池:
- 一次性开辟一些线程。我们用户直接给线程池子提交任务。线程任务的调度交给线程池来完成
from concurrent.futures import ThreadPoolExecutor def fun(name): for i in range(1000): print(name,i) if __name__ == '__main__': # 创建线程池 with ThreadPoolExecutor(50) as t: for i in range(100): t.submit(fun, name=f'线程{i}') print("线程任务执行完毕...")
- 限定创建一定数量的线程
import threading,queue,time class MyThreadPool: # 一次限制最多2个线程 def __init__(self,maxsize=2): self.maxsize = maxsize self.__pool = queue.Queue(maxsize) for _ in range(maxsize): self.__pool.put(threading.Thread) def get_thread(self): return self.__pool.get() def add_thread(self): self.__pool.put(threading.Thread) def task(i,pool): print("执行任务...", i) time.sleep(1) # 一个线程结束后再添加一个线程 pool.add_thread() if __name__ == '__main__': pool = MyThreadPool() # 假如执行6个任务 for i in range(1,6): obj = pool.get_thread() t = obj(target=task, args=(i, pool)) t.start() # 执行结果: ''' 执行任务... 1 执行任务... 2 执行任务... 3 执行任务... 4 执行任务... 5 执行任务... 6 '''
异步&协程:
- 协程的切换不同于线程切换,是由程序自身控制的,没有切换的开销。协程不需要多线程的锁机制,因为都是在同一个线程中运行,所以没有同时访问数据的问题,执行效率比多线程高很多。
- 当程序遇见了
IO操作
的时候,可以选择性的切换到其他任务上. Python3.8
之后废弃装饰器写法,而是以async
(异步)和await
(等待)代替- 协程的四种状态:
GEN_CREATED
: 等待开始执行。GEN_RUNNING
: 协程正在执行。GEN_SUSPENDED
: 在yield表达式处暂停。GEN_CLOSED
: 执行结束。
import asyncio,time async def fun1(): print("我是aaa") await asyncio.sleep(3) print("我是aaa") async def fun2(): print("我是bbb") await asyncio.sleep(2) print("我是bbb") async def fun3(): print("我是ccc") await asyncio.sleep(4) print("我是ccc") async def main(): tasks = [ asyncio.create_task(fun1()), asyncio.create_task(fun2()), asyncio.create_task(fun3()), ] await asyncio.wait(tasks) if __name__ == '__main__': t1 = time.time() asyncio.run(main()) t2 = time.time() print("耗时:",t2-t1) # 执行结果: ''' 我是bbb 我是aaa 我是ccc 我是bbb 我是aaa 我是ccc 耗时: 4.018770217895508 '''
- 协程实例:
import asyncio import datetime async def display_date(num, loop): end_time = loop.time() + 10.0 while True: print("Loop: {} Time: {}".format(num, datetime.datetime.now())) if (loop.time() + 1.0) >= end_time: break await asyncio.sleep(2) # 阻塞直到协程sleep(2)返回结果 if __name__ == '__main__': loop = asyncio.get_event_loop() # 获取一个event_loop tasks = [display_date(1, loop), display_date(2, loop)] loop.run_until_complete(asyncio.gather(*tasks)) # “阻塞"直到所有的tasks完成 loop.close() # 执行结果: ''' Loop: 1 Time: 2021-10-24 13:46:47.247362 Loop: 2 Time: 2021-10-24 13:46:47.248363 Loop: 1 Time: 2021-10-24 13:46:49.252192 Loop: 2 Time: 2021-10-24 13:46:49.252192 '''
第二章:命令行参数
获取命令行参数:
sys.argv
: 获取输入的参数列表
import sys print("参数个数为:",len(sys.argv),"个参数.") print("参数列表为:",str(sys.argv))
argparse模块:
argparse 模块
是 Python 内置的一个用于命令项选项与参数解析的模块,可以让人轻松编写用户友好的命令行接口。- 通过在程序中定义好我们需要的参数,然后 argparse 将会从
sys.argv
解析出这些参数。 argparse 模块
还会自动生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息。- 必须在命令行内执行,
python xxx.py 参数...
xxx = argparse.ArgumentParser()
创建解释器对象,参数列表:prog
: 程序的名称(默认值:sys.argv[0])usage
: 描述程序的用途description
: help信息前
显示的信息epilog
: help信息后
显示的信息- 实例:
import argparse parser = argparse.ArgumentParser(prog='程序的名称',usage='程序的用途',description='help信息前显示的信息',epilog='help信息后显示的信息')
add_argument:
xxx.add_argument()
添加参数,参数列表:metaver
: 帮助信息中显示的参数名称const
: 保存一个常量default
: 默认值type
: 参数类型,默认str
choices
: 设置参数值的范围,如果参数不是参数串,要设置type
类型required
: 是否必选,默认True
dest
: 参数名- 实例:
# 添加必选参数(位置参数) parser.add_argument('name',type=str,help='请输入你的名字') parser.add_argument('age',type=int,help='请输入你的年龄') # 添加可选参数 parser.add_argument('-s','--sex',default='男',choices=['男','女'],type=str,help='请输入你的性别')
- 实例:
# 模仿MySQL命令行登陆 import argparse #创建一个解释器对象 parser = argparse.ArgumentParser(prog='系统登录',usage='%(prog)s [otions] usage', description='系统自定义的命令行文件',epilog='my - epilog') #添加必选参数 parser.add_argument('loginType',type=str,help='登陆MySQL账户') #添加可选参数 parser.add_argument('-u',dest='user',type=str,help='你的用户名') parser.add_argument('-p',dest='password',type=str,help='你的密码') #执行解析参数 result = parser.parse_args() if (result.user == 'root' and result.password == '123456'): print('login sucess!') else: print('login fail!')
第三章:正则表达式
re.match():
re.match(r'a',xxx,参数)
仅匹配xxx
中以a
开头的字符串,匹配成功返回匹配的对象,反则返回None
- 使用
xxx.group()
匹配成功返回该字符,失败则报错 - 参数
re.I
忽略大小写 - 参数
re.M
多行匹配 - 参数
re.S
让.可以匹配换行符
- 使用
import re data = "Aagsdfh" result = re.match(r'a',data,re.I | re.M) #精确匹配 print(type(result)) print(result.group()) #执行结果: ''' <class 're.Match'> A '''
re.search():
re.search(r'a',xxx)
用于匹配a
在xxx
中第一次
出现的位置,匹配成功返回匹配的对象,反则返回None
import re data = "vAagasdfh" result = re.search(r'a',data) #精确匹配 print(result.group()) #执行结果: ''' a '''
re.findall():
- 用于在字符串中找到所匹配的
所有子串
,并以list列表
结构返回,反则返回空列表 match
和search
是匹配一次,findall
匹配所有
import re data = "<title>xxx</title><body>我是主体</body>" result = re.compile(r'<.*?>') print(result.findall(data)) #执行结果: ''' ['<title>', '</title>', '<body>', '</body>'] '''
re.finditer():
- 用于在字符串中找到所匹配的
所有子串
,但返回的结构是迭代器
,所以效率要高于re.findall()
import re data = re.finditer(r"\d+", "我的电话是12345,而不是54321") for i in data: print(i.group()) #执行结果: ''' 12345 54321 '''
re.compile():
- 用于预加载正则表达式,生成一个正则表达式对象,供
match()
、search()
、findall()
、finditer()
函数使用
import re data = r'atabac' res = re.compile(r'a') result1 = res.match(data) print(result1.group()) result2 = res.search(data,2) print(result2.group()) result3 = res.findall(data) print(result3) result4 = res.finditer(data) for i in result4: print(i.group()) #执行结果: ''' a a ['a', 'a', 'a'] a a a '''
常用匹配模式:
- 普通字符:
.
匹配除换行符外的一个字符^
匹配字符串的开头- $ 匹配字符串的结尾
|
相当于逻辑or
*
匹配出现次数(包含零次)的一个字符+
匹配出现次数(至少一次)的一个字符?
匹配出现0-1次的一个字符{x,y}
匹配指定出现x-y次数的一个字符[abc]
匹配abc中任意一个字符[^abc]
匹配不包含abc中的一个字符
- 特殊字符(元字符):
\d
匹配数字\D
匹配非数字s
匹配空白,即匹配\f\n\r\t\v
S
匹配非空白,即匹配\f\n\r\t\v
之外的w
匹配单词字符,即a-z
,A-Z
,0-9
W
匹配非单词字符
贪婪模式:
- 正则默认匹配就是贪婪模式,也就是默认去更多的匹配符合规则的数据
import re data = "<title>我是标题</title><body>我是主体</body>" result = re.compile(r'<.*>') print(result.findall(data)) #执行结果: ''' ['<title>我是标题</title><body>我是主体</body>'] '''
非贪婪模式:
- 和贪婪模式正好相反,也就是默认去更少的匹配符合规则的数据,即在筛选条件中加上
?
import re data = "<title>我是标题</title><body>我是主体</body>" result = re.compile(r'<.*?>') print(result.findall(data)) #执行结果: ''' ['<title>', '</title>', '<body>', '</body>'] '''
提取内容:
(?P<xxx>正则式)
,用于将正则式
提取出来的值赋给xxx
,xxx
为自定义的变量名
import re data = """ <title>我是标题1</title><body>我是主体1</body> <title>我是标题2</title><body>我是主体2</body> """ res = re.compile(r"<title>(?P<a>.*?)</title><body>(?P<b>.*?)</body>", re.S) obj = res.finditer(data) for i in obj: print(i.group("a")) print(i.group("b")) #执行结果: ''' 我是标题1 我是主体1 我是标题2 我是主体2 '''
第四章:操作数据库
操作MySQL数据库:
- 需要安装
pymysql
模块 ->pip install pymysql
xxx = pymysql.connect()
连接数据库,参数:host
: 数据库IP地址user
: 数据库账号password
: 数据库密码database
: 要连接的数据库名字charset
: 字符编码
yyy = xxx.cursor()
: 创建游标对象yyy.execute()
: 执行SQL语句yyy.fetchall()
: 获取全部数据yyy.fetchone()
:获取单条数据yyy.rollback()
:数据回滚
import pymysql # 创建数据库连接 con = pymysql.connect(host='localhost',user='root',password='123456',database='people',charset='utf8') # 创建一个游标对象,利用该对象进行数据库操作 try: cur = con.cursor() # 执行SQL语句 cur.execute('select * from account') result = cur.fetchall() for item in result: print(item) print("sucess!") except Exception as ex: print(ex) finally: cur.close() con.close() #执行结果: ''' ('1', '张三', '男', '河南汝州市', 'zhangsan@163.com') ('2', '李四', '女', '河南商丘市', 'lisi@163.com') sucess! '''
第五章:网络编程
服务端搭建:
- 导入
socket
模块 ->套接字
import socket
- 创建
socket
类对象xxx = socket.socket(family,type)
- 参数
family
:socket.AF_INET
: IPV4传输socket.AF_INET6
: IPV6传输socket.AF_UNIX
: UNIX传输
- 参数
type
:socket.SOCK_STREAM
: TCP协议socket.SOCK_DGRAM
: UDP协议
- 参数
- 绑定
IP地址
和端口
(元祖)xxx.bind(('IP地址',端口))
- 设置最大监听数
xxx.listen(x)
# 服务端 import socket #导入模块 # 创建 socket 对象 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #采用TCP协议 # sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #采用UDP协议 # 绑定端口和IP IP 如果为空的话,表示绑定所有IP sock.bind(("127.0.0.1",8001)) # 设置监听 sock.listen(3) print("服务已启动...") result = True while result == True: # con接收sock对象,add接收IP和端口号 con,add = sock.accept() # print(con) # print(add) print("%s 已连接成功..."%add[0]) while True: recvs = con.recv(512) print(recvs.decode("utf-8")) if recvs.decode("utf-8") == "break": break sends = input("请输入要发送给客户端的消息:") con.send(sends.encode("utf-8")) # con.sendto(sends.encode("utf-8"),("127.0.0.1",8001)) #UDP协议写法 if sends == "break": result = False break sock.close()
客户端搭建:
- 参数模块和服务器都相同
# 客户端 import socket #导入模块 # 必须和服务端的协议保持一致 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #采用TCP协议 # sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #采用UDP协议 # 连接服务器 sock.connect(("127.0.0.1", 8001)) while True: # 发送消息 sends = input("请输入要发送给服务端的消息:") sock.send(sends.encode("utf-8")) if sends == "break": break # 接收消息,recv()设置最大接收数据(单位bit) recvs = sock.recv(512) print(recvs.decode("utf-8")) # con.sendto(sends.encode("utf-8"),("127.0.0.1",8001)) #UDP协议写法 if recvs.decode("utf-8") == "break": break sock.close()
第六章:JSON
Json基本方法:
Json
是一种表示数据的语法格式,当前被Web API接口
广泛采用。json.loads()
:将json
数据转换为dict
字典json.dumps()
:将dict
字典转化为json
数据- 写入json文件时
- 使用
indent=1
可使内容换行 - 使用
ensure_ascii=False
避免乱码 - 例如:
json.dumps(字典, indent=1, ensure_ascii=False)
- 使用
- Json基本格式:
{ "one":1, "two":2, "three":[ { "four":4, "five":5 }, { "six":6, "seven":7 } ] }
这篇关于Python基础+进阶(万字总结,基础案例+执行结果)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2025-01-03用FastAPI掌握Python异步IO:轻松实现高并发网络请求处理
- 2025-01-02封装学习:Python面向对象编程基础教程
- 2024-12-28Python编程基础教程
- 2024-12-27Python编程入门指南
- 2024-12-27Python编程基础
- 2024-12-27Python编程基础教程
- 2024-12-27Python编程基础指南
- 2024-12-24Python编程入门指南
- 2024-12-24Python编程基础入门
- 2024-12-24Python编程基础:变量与数据类型