Swapping superclass from a module

Arnaud Delobelle arnodel at googlemail.com
Sat May 16 19:08:27 EDT 2009


"Emanuele D'Arrigo" <manu3d at gmail.com> writes:

> On May 16, 8:17 pm, Arnaud Delobelle <arno... at googlemail.com> wrote:
>> # 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
>
> That-is-neat! I'm impressed. It took me a while to understand it all:
> I didn't know about __subclasses__, the way you fill the dictionary is
> completely novel to me and the use of type(name, tuple, attributes)
> was also completely novel to me. But eventually I got it and it's
> quite neat. Thank you.
>
>> Of course, there are plenty of ways this could break.
>
> Uh-oh. Ok, you got me all excited and now I have to read the fine
> prints. So, how can it break?

I can think of 3 easy ways (and there may be more):

1. For simplicity I chose to ignore attributes that start with '__' but of
course in real life some of them would need to be included (__init__ &
co...).

2. It wouldn't work with multiple inheritance.

3. If the original classes are not just defined, but also used when the
module is loaded then this will cause problems.  E.g. imagine that the
file 'modfoo.py' in my example contains the additional line

    AA = A

Then when A is patched, AA will remain bound to the original class A,
and there is not much that can be done about this.


1. and 2. are only problems because my code was proof-of-concept and can
be addressed without difficulty I think.  

3. is a more serious limitation, but if your module doesn't use the
classes (i.e. it just defines them), then the method might work OK I
guess.

-- 
Arnaud



More information about the Python-list mailing list