用类作为装饰器时,区分__init__、__get__和__call__特殊方法作用和调用时机。
第一个例子:
类作为装饰器,会直接调用__init__方法,并传入func参数,此时方法的调用为类的调用,__call__此时接收方法的所有参数。
>>> class A:
def __init__(self, func, *args, **kwargs):
print(self, func, args, kwargs, sep='\n')
def __call__(self, *args, **kwargs):
print(self, args, kwargs, sep='\n')
>>> class B:
@A
def b(self, name):
print('b...', self, name, sep='\n')
<__main__.A object at 0x0000000003004F28>
<function B.b at 0x0000000002FE1C80>
()
{}
>>> tb = B()
>>> tb.b
<__main__.A object at 0x0000000003004F28>
>>> tb.b()
<__main__.A object at 0x0000000003004F28>
()
{}
>>> tb.b('abc')
<__main__.A object at 0x0000000003004F28>
('abc',)
{}
>>>
第二个例子:
类作为装饰器,会直接调用__init__方法,并传入func参数,返回的方法为__get__方法中的返回值(self),此时方法的调用为类的调用,__call__此时接收方法的所有参数。
>>> class A:
def __init__(self, func, *args, **kwargs):
print('init...', self, func, args, kwargs, sep='\n')
def __get__(self, *args, **kwargs):
print('get...', self, args, kwargs, sep='\n')
return self
def __call__(self, *args, **kwargs):
print('call...', self, args, kwargs, sep='\n')
>>> class B:
@A
def b(self, name):
print('b...', self, name, sep='\n')
init...
<__main__.A object at 0x0000000002FDD4A8>
<function B.b at 0x00000000032BB378>
()
{}
>>> tb = B()
>>> tb.b
get...
<__main__.A object at 0x0000000002FDD4A8>
(<__main__.B object at 0x0000000002FBB470>, <class '__main__.B'>)
{}
<__main__.A object at 0x0000000002FDD4A8>
>>> tb.b()
get...
<__main__.A object at 0x0000000002FDD4A8>
(<__main__.B object at 0x0000000002FBB470>, <class '__main__.B'>)
{}
call...
<__main__.A object at 0x0000000002FDD4A8>
()
{}
>>> tb.b('abc')
get...
<__main__.A object at 0x0000000002FDD4A8>
(<__main__.B object at 0x0000000002FBB470>, <class '__main__.B'>)
{}
call...
<__main__.A object at 0x0000000002FDD4A8>
('abc',)
{}
>>>