如何将一个类的现有实例方法绑定到另一个类?

6 投票
3 回答
3168 浏览
提问于 2025-04-16 21:06

我正在尝试在一个类上做一种有限的动态混入,想把第三方库中的方法绑定到我的类上。但是我尝试的所有方法都没有正确工作。我看到的所有例子都是把一个未绑定的函数绑定到一个类上,但在我的情况下,我需要把一个已经绑定的方法绑定到另一个类。

这是我正在使用的一些示例代码,包括我失败的尝试:

import types
import traceback

class Class1(object):
    output = 'class1'
    def method(self):
        print self.output

class Class2(object):
    output = 'class2'

try:
    Class2.method = types.MethodType( Class1.method, None, Class2 )
    class2 = Class2()
    class2.method()
except:
    traceback.print_exc() # TypeError: unbound method method() must be called with Class1 instance as first argument (got Class2 instance instead)

try:
    class1 = Class1()
    class2 = Class2()
    class2.method = types.MethodType( class1.method, class2, Class2 )
    class2.method()
except:
    traceback.print_exc() # TypeError: method() takes exactly 1 argument (2 given)

class1 = Class1()
class2 = Class2()
class2.method = class1.method.__get__( class2, Class2 )
class2.method() # outputs 'class1' not 'class2'

这可能吗?我是不是做错了什么?有没有我没见过的其他技巧?

3 个回答

0

你有没有想过创建一个元类,这样你就可以动态地指定父类?具体来说,就是通过重写 mro() 方法,让你在程序运行时可以随时调用它。


针对你最近的评论:你可以考虑使用一个工厂函数,在单元测试开始执行后生成你想要的类。这种方法可能和使用元类的想法很搭配。

2

对你的代码做了一些修改,希望这样能正常运行。

import types

class Class1(object):
  output = 'class1'
  def method(self):
    print self.output

class Class2(object):
  output = 'class2'

# you have to use im_func - bound or even unbound methods will fail
class1Method = Class1().method.im_func 

Class2.method = types.MethodType(class1Method, Class2(), Class2)
Class2().method() # it will print 'class2'
8

通过修改 YourClass.__bases__,可以动态地将其作为父类添加:

>>> class Base: pass
>>> class Foo(Base): pass
>>> class Bar(Base): attr = True
>>> Foo.__bases__ = (Bar,) + Foo.__bases__
>>> Foo.attr
True

另外,你可以获取绑定的方法对象,然后提取出原始函数,再把它作为你原始类的一个属性附加上去:

YourClass.method = OtherClass.bound_method.im_func

编辑:你应该修改 __bases__ 而不是 __mro__。哎呀。

撰写回答