self,printValue=False):
? ? ? ? self._printValue=printValue
? ? def __call__(self,cls):
? ? ? ? def _call():
? ? ? ? ? ? obj=cls()
? ? ? ? ? ? if self._printValue:
? ? ? ? ? ? ? ? print 'value = %r'%obj.value
? ? ? ? ? ? return obj
? ? ? ? return _call
?
? ?
>>> @test(True)
class sy(object):
? ? def __init__(self):
? ? ? ? self.value=32
?
? ? ? ?
>>> s=sy()
value = 32
>>> s
<__main__.sy object at 0x0000000003AB50B8>
>>> s.value
32
>>>?
?b.被装饰对象有参数:
>>> class test(object):
? ? def __init__(self,printValue=False):
? ? ? ? self._printValue=printValue
? ? def __call__(self,cls):
? ? ? ? def _call(*args,**kw):
? ? ? ? ? ? obj=cls(*args,**kw)
? ? ? ? ? ? if self._printValue:
? ? ? ? ? ? ? ? print 'value = %r'%obj.value
? ? ? ? ? ? return obj
? ? ? ? return _call
?
? ?
>>> @test(True)
class sy(object):
? ? def __init__(self,value):
? ? ? ? #The parameters of _call can be '(value)' in this case.
? ? ? ? self.value=value
?
? ? ? ?
>>> s=sy('hello world')
value = 'hello world'
>>> s
<__main__.sy object at 0x0000000003AB5588>
>>> s.value
'hello world'
>>>?
?总结:【1】@decorator后面不带括号时(也即装饰器无参数时),效果就相当于先定义func或cls,而后执行赋值操作func=decorator(func)或cls=decorator(cls);
? ? ? ? ? 【2】@decorator后面带括号时(也即装饰器有参数时),效果就相当于先定义func或cls,而后执行赋值操作 func=decorator(decoratorArgs)(func)或cls=decorator(decoratorArgs)(cls);
? ? ? ? ? 【3】如上将func或cls重新赋值后,此时的func或cls也不再是原来定义时的func或cls,而是一个可执行体,你只需要传入参数就可调用,func(args)=>返回值或者输出,cls(args)=>object of cls;
? ? ? ? ? 【4】最后通过赋值返回的执行体是多样的,可以是闭包,也可以是外部函数;当被装饰的是一个类时,还可以是类内部方法,函数;
? ? ? ? ? 【5】另外要想真正了解装饰器,一定要了解func.func_code.co_varnames,func.func_defaults,通过它们你可以以func的定义之外,还原func的参数列表;另外关键字参数是因为调用而出现的,而不是因为func的定义,func的定义中的用等号连接的只是有默认值的参数,它们并不一定会成为关键字参数,因为你仍然可以按照位置来传递它们。
--------------------------------------分割线 --------------------------------------