properties setting each other

Bruno Desthuilliers bruno.42.desthuilliers at websiteburo.invalid
Wed Sep 3 16:50:43 CEST 2008

mk a écrit :
> Hello everyone,
> 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)

the 'internal' prefix is already implied by the '_'. And your __init__ 
code is a useless duplication of fsetvalue, so just use the property and 
get rid of copy-pasted code.

>     def fgetvalue(self):
>         return self._internalval

the '_' prefix already means 'internal'. The convention here would be to 
name the attribute '_value' (to make clear it's the implementation 
support for the 'value' property). Also, your property getter and setter 
should also be marked as implementation using the '_' prefix - they are 
implementation detail, not part of your class API.

>     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

Hem... Notice something here ?

>         self.value = math.sqrt(self.square)
>     square = property(fgetsquare, fsetsquare)

Your fsetsquare implementation is broken - it calls itself recursively. 
You have to use different names for the property and the 'implementation 
attribute' for the property. But even if you fix this, you'll have 
another infinite recursion between the two setters.

The simplest solution : don't call one property from the other, do 
direct attribute access within the setters:

import math

class Squared2(object):
     def __init__(self, value):

     def _fgetvalue(self):
         return self._value
     def _fsetvalue(self, value):
     value = property(_fgetvalue, _fsetvalue)

     def _fgetsquare(self):
         return self._square
     def _fsetsquare(self,square):
         self._square = square
         self._value = math.sqrt(square)
     square = property(_fgetsquare, _fsetsquare)

More information about the Python-list mailing list