注入python类成员函数

时间:2018-08-03 18:52:08

标签: python functional-programming

以下代码适用于python3,但不适用于python2。为了清楚起见,我尝试将另一个类(Class1)中的成员函数注入/猴子修补到目标类(Class2)中,以便该函数使用self中的适当成员属性。

为什么它在python3中可以工作,我还可以做些什么来在python2中获得所需的行为?

class Parent:
  def foo(self):
    print("foo of class Parent: instance " + self.__class__.__name__)

  def __init__(self):
    self.d = {"foo": self.__class__.foo}

  def bar(self):
    self.d['foo'](self)
    self.d['foo'] = Child1.foo
    self.d['foo'](self)

class Child1(Parent):
  def foo(self):
    print("foo of class Child1: instance " + self.__class__.__name__)

class Child2(Parent):
  pass

Child2().bar()

1 个答案:

答案 0 :(得分:2)

您要在此处执行的操作是使用非Child2.foo的{​​{1}}调用未绑定方法self

这是非法的,Python 2将检测到该错误并提出一个Child2来解释到底是什么问题:

TypeError

在Python 3中,没有未绑定的方法对象。未绑定的方法只是普通的旧函数。因此,他们无法检查您是否试图做任何非法的事情。然后,由于实际上并没有使用TypeError: unbound method foo() must be called with Child1 instance as first argument (got Child2 instance instead) 方法内部的selfChild2的事实,因此您无需理会。


但是您不能以这种方式注入实际使用foo的{​​{1}}形式的方法。他们最终只会引发Child2Child2或调用错误的方法。它仅适用于没有理由成为方法的方法。


如果您仍然确实希望在Python 2中实现此行为,则可以通过从未绑定方法中提取函数来获得它:

TypeError

(如果您想使用更早的2.x版本,请在此处使用AttributeError而不是 self.d['foo'] = Child1.foo.__func__ 。)

现在,它根本不是一种方法,并且,如果您尝试通过描述符协议将其实际绑定到im_func或通过构造__func__来绑定,则会得到相同的旧{{ 1}}。但这是一个函数,您可以使用任何需要作为函数的参数来调用它。而且,由于您的函数对需要self的{​​{1}}参数不执行任何操作,因此它将起作用。


我们正在讨论,您几乎可以肯定希望MethodType在这里成为一种新型的类。而且,您可能想在Python 2和Python 3中使用相同的代码,而不要对两者的行为都使用不同的代码。所以:

TypeError