www.zhblog.net

Python类装饰器中的__get__与__call__方法

用类作为装饰器时,区分__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',)
{}
>>> 

展开阅读全文

评论

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 心情