猴子修补,鸭子打字和论证自我

时间:2018-01-31 21:12:06

标签: python python-2.7

当我尝试使用来自另一个类的方法修补类时,它不起作用,因为参数self的类型不正确。

例如,让我们喜欢由花哨的类__str__创建的方法A的结果:

class A:
   def __init__(self, val):
       self.val=val
   def __str__(self):
       return "Fancy formatted %s"%self.val

并希望将其重复用于无聊的课程B

class B:
   def __init__(self, val):
       self.val=val

这意味着:

 >>> b=B("B") 

 >>> #first try:
 >>> B.__str__=A.__str__
 >>> str(b)
 Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 TypeError: unbound method __str__() must be called with A instance as first argument (got nothing instead)


 >>> #second try:
 >>> B.__str__= lambda self: A.__str__(self)
 >>> str(b)
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "<stdin>", line 1, in <lambda>
 TypeError: unbound method __str__() must be called with A instance as first argument (got B instance instead)

所以在这两种情况下它都不起作用,因为参数self应该是类A的一个实例,但显然不是。

找到一种方法来进行猴子修补会很好,但我的实际问题是,为什么隐式参数self必须是“正确”类的一个实例,而不仅仅是取决于鸭子打字?

1 个答案:

答案 0 :(得分:5)

由于方法在Python 2中为类对象提供方式,实际的函数对象隐藏在未绑定的方法后面,但您可以使用im_func又名__func__属性访问它:

>>> B.__str__ = A.__str__.__func__
>>> str(B('stuff'))
'Fancy formatted stuff'

可以说,更好的方法是使用新式类和继承。

class MyStrMixin(object):
   def __str__(self):
       return "Fancy formatted %s" % self.val

然后继承MyStrMixinA中的B,然后让MRO执行此操作。