如何将一个类的实例方法monkeypatch到另一个类的实例方法?

2024-10-01 07:43:27 发布

您现在位置:Python中文网/ 问答频道 /正文

给定一个类A我可以通过

def a(self):
    pass

A.a = a

但是,如果我尝试添加另一个类B的instancemethodb,即A.b = B.b,那么调用A().b()的尝试会产生一个

TypeError: unbound method b() must be called with B instance as first argument (got nothing instead)

(而B().b()做得很好)。事实上,这两者之间是有区别的

^{pr2}$

所以

  • 怎么解决这个问题?在
  • 为什么会这样?有一些直觉上的原因,但通常情况下。。。在

奇怪的是,这在Python3中不再失败。。。在


Tags: instanceselfdefaswithpassbeargument
2条回答

当引用类实例上的方法时,该方法将绑定到该类实例。在

B().b相当于:lambda *args, **kwargs: b(<B instance>, *args, **kwargs)

我怀疑您在评估B.B.时得到了一个类似(但不完全相同)的包装引用。但是,这不是我预期的行为。在

有趣的是:

A.a = lambda s: B.b(s)
A().a()

产量:

TypeError: unbound method b() must be called with B instance as first argument (got A instance instead)

这表明B.b正在对实际方法的包装求值,包装器正在检查“self”是否具有预期的类型。我不知道,但这可能是口译员效率的问题。在

不过,这是个有趣的问题。我希望有人能附和一个更明确的答案。在

让我们:

class A(object): pass

class B(object):
    def b(self): 
        print 'self class: ' + self.__class__.__name__

当您执行以下操作时:

^{pr2}$

不是将函数附加到a,而是将未绑定方法附加到。因此python只将其作为标准属性添加,而不将其转换为a无界方法。解决方案很简单,附加底层函数:

A.b = B.b.__func__

print A.b
    # print: <unbound method A.b>
a = A()
a.b()
    # print: self class: A

我不知道未绑定方法和函数之间的所有区别(只知道第一个包含第二个),也不知道它们在内部是如何工作的。所以我无法解释原因。我的理解是方法对象(绑定与否)比函数需要更多的信息和功能,但它需要一个来执行。在

我同意自动化(更改未绑定方法的类)可能是一个不错的选择,但我可以找到不这样做的理由。因此,Python3与Python2的区别令人惊讶。我想找出这个选择的原因。在

相关问题 更多 >