Python 杂记:装饰器
简介
什么是装饰器?你平常见到的 @staticmethod, @classmethod, @property 等这些内容就是装饰器。
装饰器的本身是可调用的对象(staticmethod, classmethod, property 这些都是可调用的对象),通常我们用它来改装一个函数,例如:
def foo(fn):
print("foo() is called")
def qux():
print("qux() is called")
fn() # 调用被装饰的函数
return qux
@foo # foo 是个函数(也是可调用的对象),这里用来做装饰器,相当于调用了 bar = foo(bar)
def bar():
print("bar() is called")
bar() # bar 这个符号被 @foo 装饰器篡改了,现在它指向的是 qux 这个函数
bar() # 而 qux 函数中 fn 则指向的是原来的 bar 函数(通过 foo 函数的参数传进去的)
# 执行这段代码输出如下:
foo() is called <=== 只会在使用装饰器来定义函数时调用
qux() is called <=== 每次调用被装饰的函数,都会被调用
bar() is called
qux() is called
bar() is called
装饰器的两大特性总结:
- 装饰器可以对被装饰的符号(函数名)重新赋值,让它指向别的内容(函数替换);
- 装饰器实在函数定以后立马执行的,也就是在文件(模块)加载时执行。
使用场景举例
通过前面的示例,我们可以看到,装饰器可以用于装饰(或篡改)函数,比如:在正式进入函数体之前做一些准备工作,或者在调用函数之后做一些扫尾的工作。
利用这一特点,我们可以实现函数调用跟踪日志,例如:
def trace(fn):
def wapper(*args, **kwargs):
print("Enter into %s() ..." % fn.__name__)
ret = fn(*args, **kwargs) # 在调用被装饰函数之前和结束后打印日志
print("Leave %s()" % fn.__name__)
return ret
return wapper
@trace
def add(a, b):
print("Calculate %d + %d" % (a, b))
return a+b
@trace
def sub(a, b):
print("Calculate %d - %d" % (a, b))
return a-b
x = add(3, 2)
y = sub(3, 2)
print(x, y)
# 执行上述代码输出如下:
Enter into add() ...
Calculate 3 + 2
Leave add()
Enter into sub() ...
Calculate 3 - 2
Leave sub()
5 1