闭包
在函数调用结束后,函数内定义的变量就销毁了,有时需要保存函数内变量(比如我需要记录函数调用次数)
使用外部函数变量的内部函数就叫做闭包
条件有嵌套、有引用、有返回
nonlocal引入外部函数变量(进行修改)
1 2 3 4 5 6 7 8 9 10 11 12 13
| def fn(): num=0 def fn2(): nonlocal num num=num+1 print(num) return fn2 if __name__ == '__main__': f=fn() f() f2=fn() f() f2()
|
上述代码中f和f2中的num并不共用
装饰器
装饰器是特殊的闭包,其目的是不改变函数功能的情况下对函数做增强
构成装饰器的条件在闭包的条件下增加一个有额外功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| """ 语法1: 变量名=装饰器名(原有函数名) 变量名() """ def add_option(fn): def option(txt): print("add option") fn(txt) return option
def text(txt): print(txt) if __name__ == '__main__': txt1 = "Hello World" fn_text=add_option(text) fn_text(txt1)
|
语法2:语法糖(@装饰器名),后直接调用原函数名
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| def add_option(fn): def option(txt): print("add option") fn(txt) return option @add_option def text(txt): print(txt) if __name__ == '__main__': txt1 = "Hello World" text(txt1)
|
注意装饰器的内部函数格式要与原函数保持一致
不定参有返回值函数装饰器
1 2 3 4 5 6
| def add_option(fn): def option(*args,**kwargs): print("add option") return fn(*args,**kwargs) return option
|
多装饰器装饰
传统函数中离函数近的装饰器先装饰,由内到外
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| def add_option(fn): def option(*args, **kwargs): print("add option") return fn(*args, **kwargs) return option def add_option1(fn): def option(*args, **kwargs): print("add option1") return fn(*args, **kwargs) return option
def text(txt): print(txt) return txt if __name__ == '__main__': txt1 = "Hello World" text=add_option(text) text=add_option1(text) text(txt1) """ add option1 add option Hello World """
|
语法糖内则是按照语法糖顺序从上往下装饰
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| def add_option(fn): def option(*args, **kwargs): print("add option") return fn(*args, **kwargs) return option def add_option1(fn): def option(*args, **kwargs): print("add option1") return fn(*args, **kwargs) return option
@add_option @add_option1 def text(txt): print(txt) return txt if __name__ == '__main__': txt1 = "Hello World" text(txt1) """ add option add option1 Hello World """
|
单装饰器多函数(多参装饰器)
装饰器只能传递一个参数也就是函数,要传入多一个参数就要在外层多传递一个参数
即改造为嵌套装饰
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| def choice(flag): def add_option(fn): def option(*args, **kwargs): if flag==1: print("txt1") elif flag==2: print("txt2") return fn(*args, **kwargs) return option return add_option @choice(1) def text(txt): print(txt) return txt @choice(2) def text2(txt): print(txt+'2') return txt if __name__ == '__main__': txt1 = "Hello World" text(txt1) text2(txt1) """ txt1 Hello World txt2 Hello World2 """
|
上述代码如果不嵌套,也可等同于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| def add_option(fn): def option(*args, **kwargs): if fn.__name__ == "text": print("txt1") elif fn.__name__ == "text2": print("txt2") return fn(*args, **kwargs) return option @add_option def text(txt): print(txt) return txt @add_option def text2(txt): print(txt+'2') return txt if __name__ == '__main__': txt1 = "Hello World" text(txt1) text2(txt1) """ txt1 Hello World txt2 Hello World2 """
|
深浅拷贝
数据类型中存在可变类型(列表、字典、集合)与不可变类型
深浅拷贝是针对可变类型
浅拷贝只拷贝了对象本省,内部的元素只拷贝了一个引用(即仍指向原数据存放的堆)
对不可变类型使用深浅拷贝,效果和直接赋值一样
浅拷贝:copy()
深拷贝:deepcoy()