简单使用
def hint(func):
def wrapper(*args, **kwargs):
print('{} is running'.format(func.__name__))
return func(*args, **kwargs)
return wrapper
@hint
def hello():
print("Hello!")
我们现在对hello已经进行了装饰,当我们调用hello()时,我们可以看到如下结果。
>>> hello()
hello is running.
Hello!
值得一提的是被装饰器装饰过的函数看上去名字没变,其实已经变了。当你运行hello()后,你会发现它的名字已经悄悄变成了wrapper,这显然不是我们想要的(如下图所示)。这一点也不奇怪,因为外函数返回的是由wrapper函数和其外部引用变量组成的闭包。
>>>hello.__name__
'wrapper'
为了解决这个问题保证装饰过的函数__name__属性不变,我们可以使用functools模块里的wraps方法,先对func变量进行wraps。下面这段代码可以作为编写一个通用装饰器的示范代码,注意收藏哦。
from functools import wraps
def hint(func):
@wraps(func)
def wrapper(*args, **kwargs):
print('{} is running'.format(func.__name__))
return func(*args, **kwargs)
return wrapper
@hint
def hello():
print("Hello!")
恭喜你,你已经学会写一个比较通用的装饰器啦,并保证装饰过的函数__name__属性不变啦。当然使用嵌套函数也有缺点,比如不直观。这时你可以借助Python的decorator模块(需事先安装)可以简化装饰器的编写和使用。如下所示。
编辑带参数装饰器
from functools import wraps
def hint(coder):
def wrapper(func):
@wraps(func)
def inner_wrapper(*args, **kwargs):
print('{} is running'.format(func.__name__))
print('Coder: {}'.format(coder))
return func(*args, **kwargs)
return inner_wrapper
return wrapper
@hint(coder="John")
def hello():
print("Hello!")