properties setting each other

Maric Michaud maric at aristote.info
Wed Sep 3 10:44:10 EDT 2008


Le Wednesday 03 September 2008 15:57:50 mk, vous avez écrit :
> I try to set two properties, "value" and "square" in the following code,
> and arrange it in such way that setting one property also sets another
> one and vice versa. But the code seems to get Python into infinite loop:
>
>  >>> import math
>  >>> class Squared2(object):
>
>         def __init__(self, val):
>                 self._internalval=val
>                 self.square=pow(self._internalval,2)
>                 
>         def fgetvalue(self):
>                 return self._internalval
>                 
>         def fsetvalue(self, val):
>                 self._internalval=val
>                 self.square=pow(self._internalval,2)
>                 
>         value = property(fgetvalue, fsetvalue)
>
>         def fgetsquare(self):
>                 return self.square
>         def fsetsquare(self,s):
>                 self.square = s
>                 self.value = math.sqrt(self.square)
>                 
>         square = property(fgetsquare, fsetsquare)
>
>         
>  >>> a=Squared2(5)
>
> Traceback (most recent call last):
>    File "<pyshell#11>", line 1, in <module>
>      a=Squared2(5)
>    File "<pyshell#10>", line 5, in __init__
>      self.square=pow(self._internalval,2)
>    File "<pyshell#10>", line 19, in fsetsquare
>      self.square = s
>    File "<pyshell#10>", line 19, in fsetsquare
>      self.square = s
>    File "<pyshell#10>", line 19, in fsetsquare
>      self.square = s
>    File "<pyshell#10>", line 19, in fsetsquare
>      self.square = s
>    File "<pyshell#10>", line 19, in fsetsquare
>      self.square = s
>    File "<pyshell#10>", line 19, in fsetsquare
>
> ...
>
> Is there a way to achieve this goal of two mutually setting properties?

Your square property is not correctly defined, it recurselively call itself, 
it should be (I also avoided the extra lookup) :

         def fgetsquare(self):
                 return self._square
         def fsetsquare(self,s):
                 self._square = s
                 self.value = math.sqrt(s)

then the fsetvalue will be also be called recursively as it use the square 
property, you should also write it :

         def fsetvalue(self, val):
                 self._internalval=val
                 self._square=pow(val,2)

*but*, if you want to add more logic in the setters, you could want to add two 
extra methods :

         def _setsquare(self, v) :
                 # some extra logic here
                 self._square = s

         def fsetsquare(self,s):
                 self._setsquare(s)
                 self._setvalue = math.sqrt(s)

         def _setvalue(self, val):
                 # some extra logic here
                 self._internalval=val

         def fsetvalue(self, val):
                 self._setvalue(val)
                 self._setsquare=pow(val,2)


Note that if one property can really be computed from another, this kind of 
thing could be considered as bad design (except if the computation is heavy).

-- 
_____________

Maric Michaud



More information about the Python-list mailing list