Skip to content

装饰器

1. 装饰器的定义与用法

装饰器是一个返回值为另一个函数的函数,通常使用 @wrapper 语法形式来进行函数变换
装饰器的常见例子包括 classmethod()staticmethod()
装饰器语法只是一种语法糖
装饰器的作用可以简单理解成在不改变现有函数名称、内容以及其调用方式的基础上,为函数添加额外的功能

以下两个函数定义在语义上完全等价:

python
def f(arg):
    pass
f = staticmethod(f)

# 等价于

@staticmethod
def f(arg):
    pass

一个函数定义可以被一个或多个装饰器表达式所包装。
多个装饰器会以嵌套方式被应用。 例如以下代码:

python
@f1(arg)
@f2
def func(): pass

# 等价于

def func(): pass
func = f1(arg)(f2(func))

类也可以被装饰:就像装饰函数一样。
类装饰器表达式的求值规则与函数装饰器相同。结果随后会被绑定到类名称。

python
@f1(arg)
@f2
class Foo: pass

# 等价于

class Foo: pass
Foo = f1(arg)(f2(Foo))

2. 自定义装饰器

2.1 普通的装饰器

下面实现一个记录函数运行时间的装饰器:

python
import time

def run_time(func):
    """记录函数运行时间"""
    def wrapper(*args, **kwargs):
        begin_time = time.time()
        func(*args, **kwargs)
        end_time = time.time()
        print(f'{func.__name__}函数运行时间为:', end_time - begin_time)
    return wrapper

@run_time
def test():
    print('进入 test 函数')
    time.sleep(1)
    print('离开 test 函数')


test()
txt
进入 test 函数
离开 test 函数
test函数运行时间为: 1.0015549659729004

2.2 带参数的装饰器

为上面 run_time 装饰器加上一个参数 sleep_second:额外睡眠一段时间,延长函数运行时间;为后续的性能优化留足空间:

python
import time

def run_time(sleep_second):
    """记录函数运行时间"""
    def decorator(func):
        def wrapper(*args, **kwargs):
            begin_time = time.time()
            func(*args, **kwargs)
            time.sleep(sleep_second)
            end_time = time.time()
            print(f'{func.__name__}函数运行时间为:', end_time - begin_time)
        return wrapper
    return decorator

@run_time(1)
def test():
    print('进入 test 函数')
    time.sleep(1)
    print('离开 test 函数')


test()

执行结果如下:

txt
进入 test 函数
离开 test 函数
test函数运行时间为: 2.0029916763305664