是否可以重写类的 __call__ 方法?

And*_*rea 4 python python-3.x

我需要更改给__call__定对象的方法的行为。天真的方法是这样的:

class A(object):
    def __call__(self):
        return 1

def new_call():
    return 42


a = A()
a.__call__ = new_call
Run Code Online (Sandbox Code Playgroud)

为什么输出不是a()42?我可以利用一种解决方法来达到相同的效果吗?(不使用该类)


===========================编辑===================== ===========

根据记录,简短的回答是否定的。Python 直接在类上而不是在实例上调用“特殊方法” __call_,因此如果需要更改方法,则需要在类本身上进行更改。

mar*_*eau 5

特殊方法(又名“dunder”方法)是根据对象的进行查找的,因此要覆盖它,您需要更改类,而不是实例。另请注意,所有方法都有一个传递给它们的初始参数,通常称为self

\n

以下将执行您想要的操作(注意它如何影响该类的所有实例):

\n
class A(object):\n    def __call__(self):\n        return 1\n\ndef new_call(self):\n    return 42\n\n\na1 = A()\na2 = A()\nA.__call__ = new_call\n\nprint(a1())  # -> 42\nprint(a2())  # -> 42\n
Run Code Online (Sandbox Code Playgroud)\n

如果您只想更改特定实例,一个相对简单的解决方法是使类的方法调用__call_()特殊”的方法,例如 \xe2\x80\x94,即通过引入间接级别。

\n

这就是我的意思:

\n
# Workaround\n\nclass B(object):\n    def __call__(self):\n        return self.call_method(self)\n\n    @staticmethod\n    def call_method(self):\n        return 1\n\ndef new_call(self):\n    return 42\n\n# Create two instances for testing.\nb1 = B()\nb2 = B()\nb2.call_method = new_call  # Will only affect this instance.\n\nprint(b1())  # -> 1\nprint(b2())  # -> 42\n
Run Code Online (Sandbox Code Playgroud)\n