加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python – 如何修补`__call__`方法?

发布时间:2020-12-16 23:38:15 所属栏目:Python 来源:网络整理
导读:我似乎无法修补类实例的__call__方法(是的,我想修补单个实例,而不是所有实例). 以下代码: class A(object): def test(self): return "TEST" def __call__(self): return "EXAMPLE"a = A()print("call method: {0}".format(a.__call__))print("test method:
我似乎无法修补类实例的__call__方法(是的,我想修补单个实例,而不是所有实例).

以下代码:

class A(object):
    def test(self):
        return "TEST"

    def __call__(self):
        return "EXAMPLE"

a = A()
print("call method: {0}".format(a.__call__))
print("test method: {0}".format(a.test))
a.__call__ = lambda : "example"
a.test = lambda : "test"
print("call method: {0}".format(a.__call__))
print("test method: {0}".format(a.test))

print(a())
print("Explicit call: {0}".format(a.__call__()))
print(a.test())

输出:

call method: <bound method A.__call__ of <__main__.A object at 0x7f3f2d60b6a0>>
test method: <bound method A.test of <__main__.A object at 0x7f3f2d60b6a0>>
call method: <function <lambda> at 0x7f3f2ef4ef28>
test method: <function <lambda> at 0x7f3f2d5f8f28>
EXAMPLE
Explicit call: example
test

虽然我想输出:

...
example
Explicit call: example
test

我如何monkeypatch __call __()?为什么我不能像修补其他方法那样修补它?

虽然this answer告诉我们该怎么做(据说,我还没有测试过),但它没有解释为什么这个问题的部分原因.

解决方法

所以,正如 J.J. Hakala评论的那样,Python真正做的是调用:
type(a).__call__(a)

因此,如果我想覆盖__call__方法,我必须覆盖类的__call__,但如果我不想影响同一个类的其他实例的行为,我需要使用override__call__创建一个新类.方法.

所以如何覆盖__call__的示例如下所示:

class A(object):
    def test(self):
        return "TEST"

    def __call__(self):
        return "EXAMPLE"

def patch_call(instance,func):
    class _(type(instance)):
        def __call__(self,*arg,**kwarg):
           return func(*arg,**kwarg)
    instance.__class__ = _

a = A()
print("call method: {0}".format(a.__call__))
print("test method: {0}".format(a.test))
patch_call(a,lambda : "example")
a.test = lambda : "test"
print("call method: {0}".format(a.__call__))
print("test method: {0}".format(a.test))

print("{0}".format(a()))
print("Explicit a.__call__: {0}".format(a.__call__()))
print("{0}".format(a.test()))

print("Check instance of a: {0}".format(isinstance(a,A)))

运行它会产生以下输出:

call method: <bound method A.__call__ of <__main__.A object at 0x7f404217a5f8>>
test method: <bound method A.test of <__main__.A object at 0x7f404217a5f8>>
call method: <bound method patch_call.<locals>._.__call__ of <__main__.patch_call.<locals>._ object at 0x7f404217a5f8>>
test method: <function <lambda> at 0x7f404216d048>
example
Explicit a.__call__: example
test
Check instance of a: True

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读