鉴于课程A
,我只需通过
a
def a(self):
pass
A.a = a
但是,如果我尝试添加另一个类B
的instancemethod b
,即A.b = B.b
,则尝试调用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
所以,
奇怪的是,这在Python3中不再失败......
答案 0 :(得分:6)
让我们:
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不同。我想找出这个选择的原因。
答案 1 :(得分:1)
当您对类实例上的方法进行引用时,该方法将绑定到该类实例。
B().b
相当于:lambda *args, **kwargs: b(<B instance>, *args, **kwargs)
我怀疑你在评估B.b时会得到一个类似(但不完全相同)的包装参考。但是,这不是我预期的行为。
有趣的是:
A.a = lambda s: B.b(s)
A().a()
的产率:
TypeError:必须首先使用B实例调用未绑定方法b() 参数(取而代之的是实例)
这表明B.b
正在评估实际方法的包装器,并且包装器正在检查'self'是否具有预期类型。我不知道,但这可能与翻译效率有关。
但这是一个有趣的问题。我希望有人可以用更明确的答案来表达。