首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >注入python类成员函数

注入python类成员函数
EN

Stack Overflow用户
提问于 2018-08-04 02:52:08
回答 1查看 407关注 0票数 1

下面的代码可以在python3中运行,但不能在python2中运行。为了清楚起见,我尝试将另一个类(Class1)的成员函数注入到目标类(Class2)中,以便该函数使用来自self的适当成员属性。

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

代码语言:javascript
复制
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()
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-04 03:09:53

您在这里要做的是使用非Child2self调用未绑定的方法Child2.foo

这是非法的,Python2将检测到这一点,并引发一个TypeError来解释到底是什么问题:

代码语言:javascript
复制
TypeError: unbound method foo() must be called with Child1 instance as first argument (got Child2 instance instead)

在Python3中,没有未绑定的方法对象;未绑定的方法只是普通的旧函数。所以他们不能检查你是否在做任何违法的事情。然后,因为您实际上没有使用selffoo方法中的Child2这一事实,所以您可以逃脱惩罚。

但是您不能以这种方式注入实际使用Child2Child2-ness的方法;它们最终只会引发一个TypeErrorAttributeError,或者调用错误的方法。它只适用于一开始就没有理由成为方法的方法。

如果你真的想要在Python2中实现这种行为,你可以通过从未绑定的方法中提取函数来实现:

代码语言:javascript
复制
    self.d['foo'] = Child1.foo.__func__

(如果您想使用更早的2.x版本,请使用im_func而不是__func__。)

现在,它根本不是一个方法-如果您尝试使用描述符协议或通过构造MethodType将其实际绑定到self,您将得到相同的旧TypeError。但它是一个函数,你可以用任何你想作为函数的参数来调用它。而且,因为您的函数不会对要求其为Child2self参数执行任何操作,所以它将正常工作。

在此期间,您几乎肯定希望Parent在这里成为一个新风格的类。您可能希望在Python2和Python3中使用相同的代码,而不是在两者中为相同的行为使用不同的代码。所以:

代码语言:javascript
复制
class Parent(object): # makes it a new-style class in 2.x as well as 3.x
  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)
    # Gets __func__ if it's an unbound method (2.x), leaves it alone if not (3.x)
    self.d['foo'] = getattr(Child1.foo, '__func__', 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()
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51678541

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档