"Emanuele D'Arrigo" <man...@gmail.com> writes: > Hi everybody, > > let's assume I have a module with loads of classes inheriting from one > class, from the same module, i.e.: > > ## myFile.py > class SuperClass(object) > class SubClass1(SuperClass) > class SubClass2(SuperClass) > class SubClass3(SuperClass) > > In a separate file I also have: > > ## myOtherFile.py > class NewSuperClass(object) > > Now, let's also assume that myFile.py cannot be changed or it's > impractical to do so. Is there a way to replace the SuperClass at > runtime, so that when I instantiate one of the subclasses > NewSuperClass is used instead of the original SuperClass provided by > the first module module? > > That was the generic case. Would the solution change much if > NewSuperClass was actually inheriting from SuperClass, effectively > wedging itself between the SuperClass and the SubClasses? >
Here is an attempt to do this. Imagine there is a module 'modfoo.py' like this: -------------------------------------------------- class Base(object): def bar(self): print 'Base.bar' class A(Base): def bar(self): Base.bar(self) print 'A.bar' class B(Base): def bar(self): super(B, self).bar() print 'B.bar' -------------------------------------------------- The following script will patch the module so that all subclasses of Base in module modfoo have their new superclass changed. I called it 'patchfoo.py'. -------------------------------------------------- import modfoo # This is the new base class Wedge(modfoo.Base): def bar(self): super(Wedge, self).bar() print 'Wedge.bar' # Insert Wedge into each subclass of modfoo.Base for subclass in modfoo.Base.__subclasses__(): if subclass.__module__ != 'modfoo': continue attrs = dict(item for item in subclass.__dict__.items() if item[0][:2] != '__') name = subclass.__name__ setattr(modfoo, name, type(name, (Wedge,), attrs)) # Replace modfoo.Base with Wedge modfoo.Base = Wedge # Tests a = modfoo.A() b = modfoo.B() for obj in 'a' ,'b': call = '%s.bar()' % (obj,) print '-'*5, call exec call -------------------------------------------------- Now let's try it: marigold:junk arno$ python patchfoo.py ----- a.bar() Base.bar Wedge.bar A.bar ----- b.bar() Base.bar Wedge.bar B.bar Of course, there are plenty of ways this could break. -- Arnaud -- http://mail.python.org/mailman/listinfo/python-list