无法覆盖__call__的实现

时间:2018-06-12 12:17:10

标签: python

以此为例:

class Foo(object):
   def __init__(self, msg):
      self._msg = msg
   def __call__(self):
      return self._msg

foo = Foo('hello')
print(foo()) # Prints 'hello'
foo.__call__ = lambda _: 'bye'
print(foo()) # Prints 'hello'

我可以在 Python 2.x Python 3.x

上重现这一点

我无法找到有关此行为的文档的任何相关信息。

这对我来说看起来像是一个有效的用例,特别是在monkeypatching stuff。

是否有理由不允许这样做?

3 个答案:

答案 0 :(得分:2)

当您使用()调用对象时,它会执行在对象类型上定义的__call__方法。因此,__call__在类Foo上定义,而不是在您的实例foo上定义。如果您重新分配Foo.__call__,它就可以运行。

Foo.__call__ = lambda _: 'bye'
print(foo()) # prints 'bye'

答案 1 :(得分:1)

试试这个:

class Foo(object):
    def __init__(self, msg):
        self._msg = msg
    def __call__(self):
        return self._msg

foo = Foo('hello')
print(foo()) # Prints 'hello'

Foo.__call__ = lambda _: 'bye' #Notice the capital F, this is the class not the instance
print(foo()) # Prints 'bye'

最后一次通话应按照您的预期打印'再见'。当你调用一个实例的函数时,它实际上是指类函数(它们被定义的地方)

答案 2 :(得分:1)

通常,您可以这样做。覆盖单个实例的给定方法的实现,而不影响其余的。

这里的问题是你试图覆盖“特殊”方法。 ns调用语法在类上查找()方法,而不是实例。

以下代码显示您可以覆盖单个实例的方法实现,并且可以解决您的问题:

__call__

注意:以下内容也可以按预期工作:

class Foo(object):
    def __init__(self, msg):
        self._msg = msg
    def __call__(self):
        return self.call()      # Delegate call to instance
    def call(self):
        return self._msg

foo = Foo('hello')
other = Foo('hi')

print(foo()) # Prints 'hello'

def new_call(self):
    return "bye"

foo.call = new_call.__get__(foo, Foo)
print(foo()) # Prints 'bye'

print(other()) # Prints 'hi' (unaffected by override)

但我更喜欢明确的定义。

相关问题