装饰器背景: 在不改变原函数代码, 且保持原函数调用方法不变的情况下, 给原函数增加新的功能
(或者给类增加新属性和方法)
核心思想: 用一个函数(或者类) 去装修 一个旧函数 (或者类) , 造出一个新函数(或者新类)
尽量简单代码, 逐步理解, 装饰器原型:
Python万物皆对象, 可以随意赋值使用
def func(): print("第三: ","我是一个函数的输出结果") a = 1 print("第一: 我是一个变量 ",a) a = func #将函数名赋值给变量 print("第二: 我是一个函数名 ",a) a() >>>第一: 我是一个变量 1 >>>第二: 我是一个函数名 <function func at 0x000000000220AAE8> >>>第三: 我是一个函数的输出结果
变量作用域
# ###根据 LEGB原则, 内函数使用外函数的局部变量 def outer(): a = 0 print("我是外部函数的 a:",a) def inner(): print("我是内部函数打印的 a:",a) >>>我是外部函数的 a: 0 >>>我是内部函数打印的 a: 1
# ###引入 nonlocal, 内函数可以修改外函数 def outer(): a = 0 print("我是外部函数的 a:",a) def inner(): nonlocal a a += 1 print("我是内部函数加工过的 a:",a) >>>我是外部函数的 a: 0 >>>我是内部函数加工过的 a: 1
闭包( 延长局部变量生存时间 )
# ### 内函数 夹带 外函数的局部变量 def outer(): a = 0 print("我是外部函数打印的 a:",a) def inner(): print("我是内部函数打印的 a:",a) return inner res = outer() #res接收的是一个函数名 print("我是返回出来的内函数名: "res) res() >>>我是外部函数打印的 a: 0 >>>我是返回出来的内函数名: <function func at 0x000000000220AAE8> >>>我是内部函数打印的 a: 0
# ### 内函数 夹带 修改后的 外函数的局部变量 def outer(): a = 0 print("我是外部函数打印的 a:",a) def inner(): nonlocal a a += 1 print("我是内部函数修改过的 a:",a) return inner res = outer() #res接收的是一个函数名 print("我是返回出来的内函数名: "res) res() >>>我是外部函数打印的 a: 0 >>>我是返回出来的内函数名: <function func at 0x000000000220CA97> >>>我是内部函数修改过的 a: 1
函数名可以当做参数传递
# ### 新函数对旧函数修饰 def old(): print('我是 旧函数') def new(f): print('我是 新函数, 我可以输出 旧函数') f() new( old ) #把旧函数名当做参数, 传递给新函数, 在新函数内产生变化 >>>我是 新函数, 我可以输出 旧函数 >>>我是 旧函数
装饰器原型
# ### 利用闭包,将函数名当参数传递 def outer(f): def inner(): print("我是外部传进来的old :",f) f() print("我是修饰工,我在旧函数后显示") return inner def old(): print("我是旧函数") print("我是最初的old: ",old) print("我是返回出来的内函数inner: ",outer(old)) #outer把函数名old当参数传回函数内部进行加工, 把函数名inner返回 old = outer(old) #实际上, 旧函数名old已被重新赋值为inner print("我不是原来的old了 ",old) old() #经过改造, 虽然调用结果不变, 但是运行结果已变化 >>>我是最初的old: <function old at 0x00000000021CAA60> >>>我是返回出来的内函数inner: <function outer.<locals>.inner at 0x00000000021CAAE8> >>>我不是原来的old了 <function outer.<locals>.inner at 0x00000000021CAAE8> >>>我是外部传进来的old : <function old at 0x00000000021CAA60> >>>我是旧函数 >>>我是修饰工,我在旧函数后显示
装饰器
# ### 用 @outer 修饰 def outer(f): def inner(): print("我是外部传进来的old :",f) f() print("我是修饰工,我在旧函数后显示") return inner @outer #实际上,将 old = outer(old) 这句改成 @outer, 放在old函数上方 def old(): print("我是旧函数") old() >>>我是外部传进来的old : <function old at 0x00000000021CAA60> >>>我是旧函数 >>>我是修饰工,我在旧函数后显示