How does Subclassing Work?
Alex Martelli
aleaxit at yahoo.com
Thu Feb 22 05:36:12 EST 2001
<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
More information about the Python-list
mailing list