Python 装饰器解读
英文名: decorator
语法示例
def decorator(obj):
print("You used a decorator.")
return obj
@decorator
def func():
pass
@decorator
class clazz:
pass
可以看到, 装饰器可以应用到函数和类上.
定义
在定义时, 装饰器表现为一个可以接受1个参数的callable
, 因此, 也可以用有__call__
方法, 且该方法接受至少1个的参数的class
实现. 这个callable
返回时, 装饰器将返回一个obj, 作为新的类/函数的值.
比如, 这两种装饰器是等价的:
def function_decorator(msg):
def wrapper(clazz):
print('decorator')
print('Message:', msg)
return clazz
return wrapper
class class_decorator:
def __init__(self, msg):
self.msg = msg
def __call__(self, clazz):
print('decorator')
print('Message:', self.msg)
return clazz
带参数的装饰器
>>> def a(*args, **kwargs):
print(*args)
def dec(clazz):
class _A(clazz):
def mm():
pass
print('hook a')
return _A
return dec
>>> @a(1,2)
class A:
pass
hook a
1 2
>>> hasattr(A,'mm')
True
>>>
以上是我在 IDLE 中的运行结果, 说明在修饰器中, 如果修饰器"含参数", 那么, 这个装饰器首先会被当做一个函数处理. 在这个例子里, 相当于先执行a(1,2)
, 将返回结果作为一个装饰器应用于class A
上.
效果
假设我们已经有了一个如下的修饰器:
def decorator(*args, **kwargs):
print(*args)
def dec(clazz):
class _A(clazz):
def mm():
pass
print('hook a')
return _A
return dec
那么, 以下代码应该是等效的:
@decorator(1,2)
class Foo:
pass
等效于
dec = decorator(1, 2)
@dec
class Foo:
pass
等效于
class Foo:
pass
dec = decorator(1,2)
Foo = dec(Foo)
这三段代码得到的Foo
类应该完全一样
多层装饰器
假设有两个装饰器deco1
和deco2
, 如果这么用:
@deco1
@deco2
def func():
pass
那么等价于
func = deco1(deco2(func))
装饰器用途
链接为 Github 链接或 Python 官方文档
- Pysnooper (https://github.com/cool-RR/PySnooper): 一个 debug 用的库, 可以使开发者免于增删改
print
代码块之苦. - Python 内置的装饰器, 具体用途请看文档