python2.5开始支持函数装饰器。装饰器语法:@自动调用装饰器函数,返回可调用对象重新绑定到主体函数名。
函数装饰器用法,@装饰器函数,下一行接def 主体函数:
@decorator
def fm(arg):
pass
fm(8)
等价于
def fm(arg):
pass
fm=decorator(fm)
fm(8)
decorator:装饰器函数,返回可调用对象,与fm具有相同数目参数;
fm:主体函数,作为入参后,重新赋值为decorator返回对象;
@decorator:自动调用装饰器函数,fm作为入参,将返回对象赋值给fm。
调用主体函数时,自动调用装饰器返回的对象,因为主体函数重新赋值为装饰器返回的对象。
即,fm(8)等价于decorator(fm)(8)
主体函数fm作为装饰器函数decorator的入参,通过@decorator自动调用装饰器函数decorator,装饰器函数返回可调用对象,并且赋值给主体函数fm。
装饰器函数decorator返回的可调用对象与主体函数fm有相同数目的入参。
函数装饰器不仅可以用在函数(function),还可以用在类方法(method)上。
比如类的静态方法@staticmethod,类的特性@property。
class C:
@staticmethod
def meth(...):
pass
class C:
@property
def name(self):
pass
python装饰器函数返回任意可调用对象给主体函数,可以是原函数或新的可调用对象。
返回不可调用对象报错
>>> def f_decorator(func):
print('f_decorator被调用,返回不可调用对象')
func()
return (1,2)# 返回不可调用对象,之后调用报错
>>> @f_decorator
def testf():
print('testf被调用')
f_decorator被调用,返回不可调用对象
testf被调用
>>> testf()
Traceback (most recent call last):
File "<pyshell#18>", line 1, in <module>
testf()
TypeError: 'tuple' object is not callable
返回原函数
>>> def f_decorator(func):
print('f_decorator被调用,返回原函数')
return func
>>> @f_decorator
def testf():
print('testf被调用')
f_decorator被调用,返回原函数
>>> testf()
testf被调用
返回包装器
装饰器函数内定义一个嵌套函数,用作包装器,内部调用主体函数,返回包装器赋值给主体函数。func作为入参保持主体函数可以被调用。
>>> def f_decorator(func):
print('f_decorator被调用,返回包装器')
def f_wrapper(*args):
print('f_wrapper被调用时,调用func')
func(*args)
return f_wrapper
>>> @f_decorator
def testf():
print('testf被调用')
f_decorator被调用,返回包装器
>>> testf()
f_wrapper被调用时,调用func
testf被调用
通过类创建装饰器
构造方法接收主体函数,重写__call__()方法,并且调用主体函数。
@类名,自动将创建的实例对象赋值给主体函数名。
>>> class c_decorator:
def __init__(self,func):
self.func=func
#实例调用小括号,会自动调用 __call__
def __call__(self,*args):
print('__call__ 被调用')
self.func(*args)
# 自动将test_cd传递给构造函数,返回实例对象赋值给test_cd
>>> @c_decorator
def test_cd():
print('test_cd 被调用')
>>> test_cd()
__call__ 被调用
test_cd 被调用
通过类创建的装饰器用于装饰函数,不能装饰类方法。
>>> class c_decorator:
def __init__(self,func):
self.func=func
def __call__(self,*args):
print('__call__ 被调用')
self.func(*args)
>>> class test_c:
#无法将test_c的实例传递给test_m的self导致报错
@c_decorator
def test_m(self,*args):
print('test_m 被调用')
>>> test_c().test_m()
__call__ 被调用
Traceback (most recent call last):
File "<pyshell#35>", line 1, in <module>
test_c().test_m()
File "<pyshell#25>", line 6, in __call__
self.func(*args)
TypeError: test_m() missing 1 required positional argument: 'self'
包装器装饰类方法
将传入的func保存到f_wrapper作用域,后面可以直接调用
>>> def f_decorator(func):
print('f_decorator被调用,返回包装器')
def f_wrapper(*args):
print('f_wrapper被调用时,调用func')
# 将传入的func保存到f_wrapper作用域
# 供后面直接调用
func(*args)
return f_wrapper
>>> class test_c:
@f_decorator
def test_m(self,*args):
print('test_m 被调用')
f_decorator被调用,返回包装器
>>> test_c().test_m()
f_wrapper被调用时,调用func
test_m 被调用