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
posted @ 2020-02-23 08:18  itwhite  阅读(171)  评论(0编辑  收藏  举报