代码模板
def 装饰器(接收函数参数):
def 内部方法名(接收函数参数):
代码体
return 内部方法名
from functools import wraps
def infinite_loop(f):
@wraps(f)
def func(*args, **kwargs):
while True:
f(*args, **kwargs)
return func
@infinite_loop
def test(name):
print(name)
if __name__ == '__main__':
test("joshua")
@运行逻辑
①拦截test
②将test以参数形势传入infinite_loop
③将infinite_loop的返回值func顶替原test
就是将运行test(name)变成运行func(name),再利用闭包使func内部可以使用原test(name)
@wraps(f)
使函数保留原有属性,如果没有@wraps(f),函数属性都是func的
print(test.__name__)
// 若没有@wraps, 输出: func
// 若有@wraps, 输出: test
类中方法重写
如果方法被重写,父类方法的装饰器将失效
可以理解为:子类重写了父类方法,运行时运行的是子类方法,于是父类被重写方法的装饰器不会运行
class Base:
@test
def func(self):
print("base")
class Sub(Base):
def func(self):
print("sub")
if __name__ == '__main__':
Base().func()
print("----")
Sub().func()
# test
# base
# ----
# sub
多重装饰器
从下往上,逐步拦截
def test1(f):
def func1(*args, **kwargs):
print(f.__name__)
return f(*args, **kwargs)
return func1
def test2(f):
def func2(*args, **kwargs):
print(f.__name__)
return f(*args, **kwargs)
return func2
@test1
@test2
def main():
print("main")
if __name__ == '__main__':
main()
# func2
# main
# main
运行逻辑详解:
①准备运行main
②被test2拦截
③准备运行func2
④被test1拦截
⑤运行func1,于是接收的方法是func2
⑥运行func2,于是接收的方法是main
⑦运行main