Python进阶系列
Python进阶-网络编程-01
Python进阶-网络编程-02
Python进阶-网络编程-03
Python进阶-多任务编程-01
Python进阶-多任务编程-02
Python进阶-多任务编程-03
Python进阶-正则表达式
Python进阶-数据库编程-01
Python进阶-数据库编程-02
Python进阶-数据库编程-03
Python进阶-数据库编程-04
Python进阶-数据拷贝问题
Python进阶-模块导入问题
Python进阶-miniWeb框架
文章目录
14.1. 带参数的装饰器
-
作用:向装饰器内部传递参数
-
格式:
def test(path): def function_out(func): def function_in(): print("开始验证") func() return function_in return function_out
-
使用:
@test("login.py") def login(): print("开始登录") @test("register.py") def register(): print("开始注册") login()
-
代参装饰器的典型写法
def mylog(type): def decorator(func): def infunc(*args,**kwargs): if type == "文件": print("文件中: 日志目录") else: print("控制台: 日志记录") return func(*args,**kwargs) return infunc return decorator @mylog("文件") def fun2(a,b): print("使用功能2",a,b) if __name__ == '__main__': fun2(100,200)
14.2. 多重装饰器
- 多重装饰器:给一个函数进行多次装饰
- 装饰原则:就近原则(靠近待装饰函数的先装饰,随后一层一层装饰)
14.3. 类装饰器
-
作用:使用一个类为一个函数装饰, 主要思路就是返回一个增加了新功能的函数对象,只不过这个函数对象是一个类的实例对象。由于装饰器是可调用对象,所以必须在类里面实现__call__方法,这样由类生成的各种实例加上()就可以运行。
-
类的书写
- 必须有两个方法
-
__init__
,必须接收装饰器传递的参数 func -
__call__
,建立装饰器时自动调用@类名 带装饰的函数 class Test(object): def __init__(self,func): self.func = func def __call__(self, *args, **kwargs): print("call") self.func()
-
- 必须有两个方法
-
不带参数的类装饰器
import time class Decorator: def __init__(self, func): self.func = func def defer_time(self): time.sleep(5) print("延时结束了") def __call__(self, *args, **kwargs): self.defer_time() self.func() @Decorator def f1(): print("延时之后我才开始执行") f1()
-
带参数的类装饰器
import time class Decorator: def __init__(self, func): self.func = func def defer_time(self, time_sec): time.sleep(time_sec) print(f"{time_sec}s延时结束了") def __call__(self, time): self.defer_time(time) self.func() @Decorator def f1(): print("延时之后我才开始执行") f1(5)
-
对象名()
调用对象__call__()
14.4. GIL锁引入
- 监控资源的竞争情况htop
- 资源的消耗情况
- 单进程 1核
- 多进程 多核
- 多线程 多核但是很低 GIL锁的问题
14.5. GIL概念及影响
- GIL 全局解释器锁
- GIL跟python语言没有关系,python底层解释器Cpython的问题
- GIL锁释放的情况
- 线程执行完毕释放
- I/O阻塞的时候释放
- python 3.x使用计时器(执行时间达到阈值后,当前线程释放GIL)
14.6. GIL解决方案
- 解决方案
- 更换解释器
Jpython
pypy
- 用进程替换线程 进程会占用更多的系统资源子线程
- 用c语言实现
(test.c -> libtest.so -> python加载)
- 更换解释器
14.7. python中可变和不可变
-
可变类型:创建后可以继续修改对象的内容
- 包含:字典、列表
-
不可变类型:一旦创建就不可修改的对象
-
包含:数字、字符串、元组
-
当内容发生修改,计算机重新分配一块内存空间
-
14.8. 简单可变类型拷贝
-
深拷贝:
- 会产生新的空间
- 能够保持各自的独立性
- 如果拷贝的对象,子对象也会拷贝(产生新的空间)
-
代码实例:
# 定义list1列表 list1 = [1,2,3] print("list1 =",list1,id(list1)) # 定义list2列表,深拷贝list1 list2 = copy.deepcopy(list1) print("list2 =",list2,id(list2)) # 改变list2的数据 list2.append(7) print("list2 =",list2,id(list2)) # list1不发生变化,能够保证数据的独立性 print("list1 =",list1,id(list1))
-
浅拷贝:
- 会产生新的空间
-
能够保持各自的独立性
-
如果拷贝的对象,子对象也会拷贝(产生新的空间)
-
代码实例:
# 定义list1列表 list1 = [1,2,3] print("list1 =",list1,id(list1)) # 定义list2列表,深拷贝list1 list2 = copy.copy(list1) print("list2 =",list2,id(list2)) # 改变list2的数据 list2.append(7) print("list2 =",list2,id(list2)) # list1不发生变化,能够保证数据的独立性 print("list1 =",list1,id(list1))
-
-
简单可变类型的拷贝总结:
简单可变类型的数据不管深拷贝还是浅拷贝,都会产生新的空间,而且保持各自的独立性
14.9. 复杂可变类型拷贝
-
深拷贝:拷贝的顶层对象和对象的子对象,子对象会产生新的内存空间
-
代码实例:
A = [1, 2, 3] B = [4, 5, 6] C = [A, B] print("A = ", A, id(A)) print("C = ", C, id(C)) D = copy.deepcopy(C) print("D = ", D, id(D)) print("D[0] =",id(D[0])," C[0] =",id(C[0])," A =",id(A)) A[0] = 10 print("D[0] =", D[0], id(D[0])) print("D = ", D, id(D)) print("A = ", A, id(A))
-
-
浅拷贝:拷贝的是顶层对象的值,子对象不会拷贝(只是引用子对象)
-
代码实例
A = [1,2,3] B = [4,5,6] C = [A,B] print("A = ",A,id(A)) print("B = ",B,id(B)) print("C = ",C,id(C)) print("C[0] =",C[0],id(C[0])) D = copy.copy(C) print("D = ",D,id(D)) print("D[0] =",D[0],id(D[0])) A[0] = 10 print("D[0] =",D[0],id(D[0])) print("D = ",D,id(D))
-
14.10. 简单不可变类型拷贝
-
深拷贝:副本和源指向同一个空间
-
代码实例
tuple1 = (1, 2, 3) print("tuple1= ", tuple1, id(tuple1)) tuple2 = copy.deepcopy(tuple1) print("tuple2= ", tuple2, id(tuple2))
-
-
浅拷贝:副本和源指向同一个空间
-
代码实例
tuple1 = (1,2,3) print("tuple1 =",tuple1,id(tuple1)) tuple2 = copy.copy(tuple1) print("tuple2 =",tuple2,id(tuple2))
-
14.11. 复杂不可变类型拷贝
-
深拷贝:看数据具体是可变还是不可变的,如果数据是可变的,会产生新的空间,保持数据的独立性。如果是不可变类型,不会产生新的空间,无法保证数据的独立性
-
代码实例
A = [1, 2, 3] B = [4, 5, 6] C = (A, B) print("C =", C, id(C)) D = copy.deepcopy(C) print("D =", D, id(D)) D[0][0]=10 print("C =", C, id(C)) print("D =", D, id(D))
-
-
浅拷贝:直接引用,不会产生新的空间,无法保证数据的独立性
-
代码实例
A = [1,2,3] B = [4,5,6] C = (A,B) print("C =",C,id(C)) D = copy.copy(C) print("D =",D,id(D))
-
14.12. 切片拷贝、字典拷贝
-
切片拷贝:浅拷贝(如果是简单可变类型,底层会产生新的空间)
-
代码实例1
list1 = [1, 2, 3, 4, 5, 6, 7] print("list1 =", list1, id(list1)) list2 = list1[:] print("list2 =", list2, id(list2))
-
代码实例2
A = [1,2,3] B = [4,5,6] C = (A,B) print("C = ",C,id(C)) D = C[:] print("D = ",D,id(D))
-
-
字典拷贝:浅拷贝
-
代码实例
dict1 = {"age":[1,2]} print("dict1 =",dict1,id(dict1)) dict2 = dict1.copy() print("dict2 =",dict2,id(dict2)) dict1['age'][0] = 100 print("dict1 =",dict1,id(dict1)) print("dict2 =",dict2,id(dict2))
-