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

S

Skip Montanaro

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
 
M

Michele Simionato

Skip Montanaro said:
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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,830
Latest member
HeleneMull

Latest Threads

Top