[Tutor] calling setters of superclasses

Peter Otten __peter__ at web.de
Sat Dec 18 11:06:04 CET 2010


Gregory, Matthew wrote:

> Hi all,
> 
> Consider the following classes where PositiveX should constrain the
> attribute _x to be positive and SmallX should further constrain the
> attribute _x to be less than 10.
> 
> class PositiveX(object):
>     def __init__(self):
>         self._x = 1
>     @property
>     def x(self):
>         return self._x
>     @x.setter
>     def x(self, val):
>         if val < 0:
>             raise ValueError('Negatives not allowed')
>         self._x = val
> 
> class SmallX(PositiveX):
>     @property
>     def x(self):
>         return self._x
>     @x.setter
>     def x(self, val):
>         # How do I call the superclass' @x.setter
>         super(SmallX, self).__setattr__('x', val)
>         if val > 10:
>             raise ValueError('Big values not allowed')
>         self._x = val
> 
> I thought I could call the superclass setter first to ensure the value was
> positive, but I'm getting an infinite recursion.  I also tried:
> 
>   super(SmallX, self).x = val
> 
> but I get this:
> 
>   AttributeError: 'super' object has no attribute 'x'
> 
> I'm fully confused and, therefore, likely doing something stupid.

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:

class SmallX(PositiveX):
    @property
    def x(self):
        return self._x
    @x.setter
    def x(self, val):
        if val > 10:
            raise ValueError('Big values not allowed')
        PositiveX.x.__set__(self, val)

Personally, I would more or less follow Alan's advice and do something like

class PositiveX(object):
    def __init__(self):
        self._x = 1
    def check_x(self, val):
        if val < 0:
            raise ValueError('Negatives not allowed')
    @property
    def x(self):
        return self._x
    @x.setter
    def x(self, val):
        self.check_x(val)
        self._x = val

class SmallX(PositiveX):
    def check_x(self, val):
        super(SmallX, self).check_x(val)
        if val > 10:
            raise ValueError('Big values not allowed')

Peter





More information about the Tutor mailing list