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