开发者

How do I bind an existing instance method in one class to another class?

I'm trying to do a limited form of dynamic mixin on a class, taking methods from a third-party library class and binding them to my class. But nothing I've tried has worked correctly. All examples I've seen elsewhere bind a unbou开发者_运维技巧nd function to a class but, in my case, I need to bind an already bound method to a different class.

Some example code I've been working with, with my failed attempts included:

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'

Is this possible? Am I doing something wrong? Is there another technique I haven't seen?


Add it as a parent class dynamically, by modifying YourClass.__bases__:

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

Alternatively, get the bound method object and extract the original function, then attach that as an attribute of your original class:

YourClass.method = OtherClass.bound_method.im_func

EDIT: you modify __bases__ not __mro__. Oops.


Some modification in your code, hope It would work.

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'


Have you considered creating a metaclass that would allow you to dynamically assign parent classes by overriding mro() in a way that would allow you to call it later in execution?


In response to your recent comment: you could perhaps use a factory function to produce the classes desired after the unit tests begin execution. This might work well with the idea of utilizing a metaclass.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜