How does Subclassing Work?

s713221 at student.gu.edu.au s713221 at student.gu.edu.au
Thu Feb 22 20:45:31 EST 2001


Alex Martelli wrote:
> 
> <s713221 at student.gu.edu.au> wrote in message
> news:3A943A45.2E433767 at student.gu.edu.au...
> > Recently I tried to write a piece of code that subclassed Canvas.py from
> > the Tkinter distribution, where I overwrote CanvasItem. Now I was hoping
> > that all calls to Arc, Line etc. (which weren't overwritten) would call
> > my modified CanvasItem, but it seems they were calling the unmodified
> > CanvasItem - which isn't what I wanted.
> 
> It's what I would expect, though; the 'class' statement for (e.g.)
> Arc was already executed, right when you imported Canvas, and,
> at that time, it got the original CanvasItem class to use as the
> base -- it didn't get your subclassed version.
> 
> > Other than copy all of Canvas.py into my module and redefine everything,
> > is there a way I can get this to work as expected without rewriting
> > Canvas.py? What I was trying to do was alter Canvas so that I could
> > create classes that would make complex items.
> 
> I hesitate to suggest it, but... if you went through all the classes
> of interest, currently set to inherit from the original CanvasItem,
> and changed that portion of their __bases__ to your modified version;
> and also set the CanvasItem attribute of the Canvas module to refer
> to your modified version; things would probably work as you want.
> 
> Here's a toy example to indicate what I mean...:
> 
> == Original.py
> class OriginalItem:
>     def __init__(self, *whatever):
>         print "OriginalItem",whatever
> 
> class Derived1(OriginalItem):
>     def __init__(self, *whatever):
>         print "Derived1",whatever
>         apply(OriginalItem.__init__, (self,)+whatever)
> 
> class Derived2(OriginalItem):
>     def __init__(self, *whatever):
>         print "Derived2",whatever
>         apply(OriginalItem.__init__, (self,)+whatever)
> == end
> 
> == Tweak.py
> import Original
> 
> baseClass = Original.OriginalItem
> class TweakedItem(baseClass):
>     def __init__(self, *whatever):
>         print "TweakedItem",whatever
> 
> for key,val in Original.__dict__.items():
>     if type(val)==type(baseClass):
>         if val is baseClass:
>             setattr(Original, key, TweakedItem)
>         else:
>             if val.__bases__ == (baseClass,):
>                 val.__bases__ = (TweakedItem,)
> 
> x = Original.Derived1("foo","bar")
> y = Original.Derived2("bar","baz")
> == end
> 
> This is not very general (though it would suffice for
> your specific need), as it only handles single-base
> classes etc, but it's not hard to generalize it along
> this axis.
> 
> I do wonder about the appropriateness of such "black
> magick" to actual production code, though.
> 
> Alex

To true. Maybe the cut-paste-alter method is better after all.

Joal Heagney/AncientHart



More information about the Python-list mailing list