[Tutor] calling setters of superclasses

Hugo Arts hugo.yoshi at gmail.com
Sat Dec 18 17:59:41 CET 2010


On Sat, Dec 18, 2010 at 11:06 AM, Peter Otten <__peter__ at web.de> wrote:
>
> I don't think /how/ you are trying it is stupid though I'm not so sure about
> /what/ .
>
> I didn't get it to work with super() either, so here's Plan B till someone
> is going to enlighten both of us:
>

By no means a solution, but I've spent some time with this in the
python debugger and have some ideas.

The problem is not super, as it does its job at calling __setattr__ of
the base object class. __setattr__, however, resolves to the x object
that is bound to self, which is SmallX.x, and not PositiveX.x, and
this is what causes the recursion.

So what you actually need is something like super(SmallX,
self).x.__set__, but that unfortunately doesn't work either since
super will use __getattr__ to resolve x, which will just result in the
property getter being called. So in general, properties don't jive
well with inheritance of their containing objects. I'm not sure if
this behavior can be considered a bug.

My idea would be to create separate descriptor classes and contain the
constraints within them. The functionality has nothing to do with the
containing class anyway, so it might actually simplify the design.
Here's the basic idea:

class UnsignedProp(object):
    def __init__(self, val):
        self.x = val
    def __get__(self, instance, owner):
        return self.x
    def __set__(self, instance, val):
        if val < 0: raise ValueError("Negatives not allowed")
        self.x = val

class SmallProp(UnsignedProp):
    def __set__(self, instance, val):
        if val > 10: raise ValueError("value too large")
        super(SmallProp, self).__set__(instance, val)

class X(object):
    x = SmallProp(1)
    y = UnsignedProp(1)

a = X()
a.x = 5
a.x = 25 # will raise ValueError


More information about the Tutor mailing list