繁体   English   中英

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

[英]How to monkeypatch one class's instance method to another one?

鉴于一类A ,我只是可以添加一个instancemethod a通过

def a(self):
    pass

A.a = a

但是,如果我尝试添加另一个B类的instancemethod b ,即Ab = Bb ,则调用A().b()的尝试产生一个

TypeError :必须使用B实例作为第一个参数调用未绑定方法b() (没有任何内容)

(而B().b()很好)。 确实存在差异

A.a -> <unbound method A.a>
A.b -> <unbound method B.b>  # should be A.b, not B.b

所以,

  • 如何解决这个问题?
  • 为什么会这样? 它似乎不直观,但通常Guido有一些很好的理由......

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

让我们:

class A(object): pass

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

当你这样做时:

A.b = B.b

您没有将函数附加到A,而是附加未绑定的方法 因此,python只将其添加为标准属性,并且不将其转换为A-unbounded方法。 解决方案很简单,附加底层功能:

A.b = B.b.__func__

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

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

我同意自动执行此操作(更改未绑定方法的类)可能是一个不错的选择,但我可以找到不这样做的理由。 令人惊讶的是,python 3与python 2不同。我想找出这个选择的原因。

当您对类实例上的方法进行引用时,该方法将绑定到该类实例。

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

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

有趣的是:

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

收益率:

TypeError:必须使用B实例作为第一个参数调用未绑定方法b()(改为获取A实例)

这表明Bb正在评估实际方法的包装器,并且包装器检查'self'是否具有预期类型。 我不知道,但这可能与翻译效率有关。

这是一个有趣的问题。 我希望有人可以提出一个更明确的答案。

暂无
暂无

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

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