Python:将方法从一个类分配给另一个类的实例

nin*_*o64 2 python

我想使用new.instancemethod将函数(aFunction)从一个类(A)分配给另一个类(B)的实例.我不知道如何让aFunction允许自己应用于B的实例 - 目前我收到一个错误,因为aFunction期望在A的实例上执行.

[注意:我无法使用__class__属性将实例强制转换为A,因为我正在使用的类(在我的示例中为B)不支持类型转换]

import new

class A(object):
    def aFunction(self):
        pass

#Class which doesn't support typecasting
class B(object): 
    pass

b = B()
b.aFunction = new.instancemethod(A.aFunction, b, B.__class__)
b.aFunction()
Run Code Online (Sandbox Code Playgroud)

这是错误:

TypeError: unbound method aFunction() must be called with A instance as first argument (got B instance instead)
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 6

new.instancemethod需要一个功能.A.aFunction是一种未绑定的方法.那不是一回事.(您可能想尝试加入一些打印语句来显示所有的东西involved- A.aFunction(),A().aFunction等和它们的类型,以帮助理解.)

我假设你没有描述符如何工作.如果你不想学习所有的血腥细节,那么实际发生的是你aFunction在类定义中的声明会从函数中创建一个非数据描述符.这是一个神奇的事情,这意味着,根据您访问它的方式,您将获得未绑定的方法(A.aFunction)或绑定方法(A().aFunction).

如果你修改aFunction为a @staticmethod,这实际上是有效的,因为对于静态方法而言A.aFunction,A().aFunction它们只是函数.(我不确定标准是否保证是真的,但是很难看出其他人会如何实现它.)但是如果你想要"aFunction允许自己应用于B的实例",那么静态方法不会帮助你.

如果你真的想要获得底层函数,有很多方法可以做到; 我认为这是帮助您理解描述符如何工作的最明确的:

f = object.__getattribute__(A, 'aFunction')
Run Code Online (Sandbox Code Playgroud)

另一方面,最简单的可能是:

f = A.aFunction.im_func
Run Code Online (Sandbox Code Playgroud)

然后,调用new.instancemethod是如何将该函数转换为可以作为B类实例的常规方法调用的描述符:

b.aFunction = new.instancemethod(f, b, B)
Run Code Online (Sandbox Code Playgroud)

打印出大量数据可以使事情变得更加清晰:

import new

class A(object):
  def aFunction(self):
    print self, type(self), type(A)

#Class which doesn't support typecasting
class B(object): 
    pass

print A.aFunction, type(A.aFunction)
print A().aFunction, type(A().aFunction)
print A.aFunction.im_func, type(A.aFunction.im_func)
print A().aFunction.im_func, type(A().aFunction.im_func)

A.aFunction(A())
A().aFunction()

f = object.__getattribute__(A, 'aFunction')
b = B()
b.aFunction = new.instancemethod(f, b, B)
b.aFunction()
Run Code Online (Sandbox Code Playgroud)

你会看到这样的事情:

<unbound method A.aFunction> <type 'instancemethod'>
<bound method A.aFunction of <__main__.A object at 0x108b82d10>> <type 'instancemethod'>
<function aFunction at 0x108b62a28> <type 'function'>
<function aFunction at 0x108b62a28> <type 'function'>
<__main__.A object at 0x108b82d10> <class '__main__.A'> <type 'type'>
<__main__.A object at 0x108b82d10> <class '__main__.A'> <type 'type'>
<__main__.B object at 0x108b82d10> <class '__main__.B'> <type 'type'>
Run Code Online (Sandbox Code Playgroud)

唯一没有显示的是创建绑定和未绑定方法的魔力.为此,你需要研究一下A.aFunction.im_func.__get__,在这一点上,你最好还是阅读描述符,而不是试图自己分开.

最后一件事:正如brandizzi指出的那样,这是你几乎不想做的事情.替代方案包括:写aFunction为自由函数而不是方法,所以你只需要调用b.aFunction(); 分解出,做实际工作的功能,并且有A.aFunctionB.aFunction叫它; 有B骨料的A并向其转交; 等等