注入一个python类成员函数
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了注入一个python类成员函数相关的知识,希望对你有一定的参考价值。
以下代码适用于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()
你在这里要做的是用一个不是Child2.foo
的self
来调用未绑定的方法Child2
。
这是非法的,Python 2将检测到并提出一个TypeError
,它解释了什么是错误的:
TypeError: unbound method foo() must be called with Child1 instance as first argument (got Child2 instance instead)
在Python 3中,没有未绑定的方法对象;未绑定的方法只是普通的旧函数。因此,他们无法检查您是否正在尝试做任何违法行为。然后,因为你实际上没有使用self
在Child2
方法中的foo
这一事实,你就可以逃脱它。
但你不能用这种方式注入实际使用Child2
的Child2
-ness的方法;他们最终会提高TypeError
或AttributeError
或者说错误的方法。它只适用于首先没有理由成为方法的方法。
如果你真的想在Python 2中使用这种行为,你可以通过从未绑定方法中提取函数来获得它:
self.d['foo'] = Child1.foo.__func__
(如果你想使用更老的2.x,那就使用im_func
而不是__func__
。)
现在,它根本不是一种方法 - 如果你试图用描述符协议实际将它绑定到self
或者通过构造一个MethodType
,你将获得相同的旧TypeError
。但它是一个函数,你可以用你想要的任何参数作为函数来调用它。并且,因为你的函数对那个需要它是self
的Child2
参数没有做任何事情,所以它会起作用。
虽然我们在这里,你几乎肯定希望Parent
成为一个新式的课程。您可能希望在Python 2和Python 3中使用相同的代码,而不是在两者中使用相同行为的不同代码。所以:
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()
以上是关于注入一个python类成员函数的主要内容,如果未能解决你的问题,请参考以下文章