Как связать существующий метод экземпляра в одном классе с другим классом?

Я пытаюсь сделать ограниченную форму динамического mixin на классе, используя методы из стороннего класса библиотеки и привязывая их к моему классу. Но ничто из того, что я пробовал, не сработало правильно. Все примеры, которые я видел в других местах, связывают несвязанную функцию с классом, но в моем случае мне нужно привязать уже связанный метод к другому классу.

Пример кода, с которым я работал, с моими неудачными попытками:

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' 

Это возможно? Я делаю что-то неправильно? Есть ли еще одна техника, которую я не видел?

Добавьте его в качестве родительского класса динамически, изменив значение 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 

EDIT: вы изменяете __bases__ not __mro__ . К сожалению.

Некоторая модификация в вашем коде, надеюсь, что это сработает.

 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' 

Рассматривали ли вы создание метакласса, позволяющего динамически назначать родительские классы, переопределяя mro() таким образом, чтобы вы могли называть его позже в процессе выполнения?


В ответ на ваш недавний комментарий: возможно, вы можете использовать заводскую функцию для создания классов, которые желательны после начала модульных тестов. Это может хорошо работать с идеей использования метакласса.