Skip Montanaro <sk**@pobox.com > wrote in message news:<ma******* *************** *************** @python.org>...
I just stumbled upon a bug in some group-written code. We have this sort of
class hierarchy:
class X(object):
...
class A(X):
def __init__(...):
self.attr = 0.0
def GetAttr(self):
return self.attr
def SetAttr(self, a):
self.attr = a
class B(A):
...
class C(B):
def set_attr(self, a):
...
def get_attr(self):
...
attr = property(get_at tr, set_attr, None, None)
Each of the four classes is defined in a different module. The author of A
was not aware that it was a new-style class and coded it like a classic
class. The author of C (different person) apparently knew it was new-style
and took advantage of that fact to use property(), but didn't notice there
was already an attribute named "attr" two levels up.
This of course all gets to the Zen bit: "Flat is better than nested", and
I'll use that as an argument for flatter hierarchies in the future.
Nonetheless, what would be the effect of such an attribute stomping? Do I
just have multiple ways to change self.attr, assuming __slots__ hasn't been
declared? This seems like something perhaps pychecker should notice, but
can it?
Thx,
Skip
I have run in this kind of troubles when working with Zope. Zope
hierarchies
as the best example of spaghetti-inheritance I have seen till now;
just today I
was looking at the CMF BaseFolder class: it has 33 ancestors (33!)
with definitions scattered in dozen of modules, packages and
subpackages,
and multiple inheritance abused at ridicoulous levels: how in they
hell they believe I can keep track of all the attributes defined in 33
ancestors??
So, I have written a routine to travel the MRO of the any class I
define;
the routine checks that I am not overriding accidentally an already
defined
attribute (which is pretty likely for what I am doing now and has
already bitten me and my coworkers a couple of times). Unfortunately
I cannot use metaclasses, so I can only get the shadowing attribute
warning
after the class creation and not before, and I have to invoke the
checking
function each time I define a new class (i.e. it is not automatic).
But anyway it helps a bit.
Michele Simionato