繁体   English   中英

Python装饰器 - 类中的__call__

[英]Python Decorators - __call__ in class

我试图理解Python装饰器,我试图写一个等效的程序到这个:

class myDecorator(object):
   def __init__(self, f):
      print ("inside myDecorator.__init__()")
      f() # Prove that function definition has completed

   def __call__(self):
      print ("inside myDecorator.__call__()")

@myDecorator
def aFunction():
   print ("inside aFunction()")

print ("Finished decorating aFunction()")

aFunction()

问题是我不理解如何通过最后调用aFunction()来调用类的__call__方法。

aFunction()是否被myDecorator.__call__(aFunction)取代。 你能帮我么? 没有装饰器的等效程序怎么样?

谢谢!

代码的输出是

inside myDecorator.__init__()
inside aFunction()
Finished decorating aFunction()
inside myDecorator.__call__()

首先,你知道吗,@ decorator语法是什么意思?

@decorator
def function(a):
    pass

只是另一种说法:

def function(a):
    pass
function = decorator(function)

所以,在你的情况下

@myDecorator
def aFunction():
   print ("inside aFunction()")

意思就是

def aFunction():
    print ("inside aFunction()")
aFunction = myDecorator(aFunction)

首先,您基本上创建了一个myDecorator类的新实例,调用它的构造函数(__init__)并向其传递一个aFunction函数对象。 然后,它执行打印和给定的功能。 另外,请注意,这是在解释器加载函数时发生的,而不是在执行时加载,所以如果你从这个文件导入一些东西,那么它将被执行,而不是在使用或调用时。

然后,当aFunction仍然引用myDecorator实例时,执行aFunction()会使它调用myDecorator的__call__方法,该方法执行。 注意,在这种情况下, f()表示与f.__call__(f)相同,因为__call__方法用于启用和覆盖默认对象的调用行为(在简化中,任何对象在定义了__call__方法时都是可__call__ )。

如果要在调用时执行aFunction,则应将其分配给__init__实例变量,并在myDecorator的__call__中调用它。

afunction正在由类的实例代替myDecorator 该类有一个__call__方法,因此可以像函数一样__call__该实例。 因此,假设它的签名是兼容的(通常装饰器返回使用*args**kwargs ),该实例可以用作原始函数的替代。

通常, __call__方法会调用包装函数。 __init__中执行通常是不正确的; __init__应该将对包装函数的引用存储为实例属性,以便__call__可以调用它。

这就是装饰器的全部目的:用装饰器返回的函数替换(或者更常见地,换行)函数。 在你的情况下, aFunction正在被aFunction一个实例myDecorator ,所以当你调用aFunction()你实际上是在调用那个实例:在Python中,调用一个类实例会调用它的__call__方法。

定义一个装饰函数与此完全相同:

def aFunction():
    print("inside aFunction()")
aFunction = myDecorator(aFunction)

当然,通常,包装函数在执行任何操作后都会调用原始函数。

这是一个修复:

class myDecorator(object):
   def __init__(self, f):
      print ("inside myDecorator.__init__()")
      self.f = f #Store the function being wrapped

   def __call__(self):
      print ("inside myDecorator.__call__()")
      self.f() # Call the wrapped function

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM