classic and property() version of same attribute - yikes!

Michele Simionato michele.simionato at gmail.com
Thu Jul 15 04:42:01 EDT 2004


Skip Montanaro <skip at pobox.com> wrote in message news:<mailman.393.1089830300.5135.python-list at 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_attr, 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



More information about the Python-list mailing list