Swapping superclass from a module
Peter Otten
__peter__ at web.de
Sun May 17 03:24:32 EDT 2009
Terry Reedy wrote:
> Steven D'Aprano wrote:
>> On Sat, 16 May 2009 09:55:39 -0700, Emanuele D'Arrigo wrote:
>>
>>> Hi everybody,
>>>
>>> let's assume I have a module with loads of classes inheriting from one
>>> class, from the same module, i.e.:
>> [...]
>>> 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's called "monkey patching" or "duck punching".
>>
>> http://en.wikipedia.org/wiki/Monkey_patch
>>
>> http://wiki.zope.org/zope2/MonkeyPatch
>>
>> http://everything2.com/title/monkey%2520patch
>
> If the names of superclasses is resolved when classes are instantiated,
> the patching is easy. If, as I would suspect, the names are resolved
> when the classes are created, before the module becomes available to the
> importing code, then much more careful and extensive patching would be
> required, if it is even possible. (Objects in tuples cannot be
> replaced, and some attributes are not writable.)
It may be sufficient to patch the subclasses:
$ cat my_file.py
class Super(object):
def __str__(self):
return "old"
class Sub(Super):
def __str__(self):
return "Sub(%s)" % super(Sub, self).__str__()
class Other(object):
pass
class SubSub(Sub, Other):
def __str__(self):
return "SubSub(%s)" % super(SubSub, self).__str__()
if __name__ == "__main__":
print Sub()
$ cat main2.py
import my_file
OldSuper = my_file.Super
class NewSuper(OldSuper):
def __str__(self):
return "new" + super(NewSuper, self).__str__()
my_file.Super = NewSuper
for n, v in vars(my_file).iteritems():
if v is not NewSuper:
try:
bases = v.__bases__
except AttributeError:
pass
else:
if OldSuper in bases:
print "patching", n
v.__bases__ = tuple(NewSuper if b is OldSuper else b
for b in bases)
print my_file.Sub()
print my_file.SubSub()
$ python main2.py
patching Sub
Sub(newold)
SubSub(Sub(newold))
Peter
More information about the Python-list
mailing list