FAQ
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)

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?

Search Discussions

  • Wojtek Walczak at Sep 3, 2008 at 2:31 pm

    On Wed, 03 Sep 2008 15:57:50 +0200, mk wrote:

    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:
    Is there a way to achieve this goal of two mutually setting properties?
    My attempt:
    ---
    import math

    class Square(object):
    def __init__(self, val):
    self._square = pow(val, 2)
    self._value = math.sqrt(self.square)

    def getsquare(self):
    return self._square

    def setsquare(self, square):
    self._square = square
    self._value = math.sqrt(self._square)

    square = property(getsquare, setsquare)

    def getvalue(self):
    return self._value

    def setvalue(self, value):
    self._value = value
    self._square = math.pow(value, 2)

    value = property(getvalue, setvalue)


    a = Square(5)
    print a.square
    print a.value
    a.value = 10
    print a.square
    print a.value
    a.square = 64
    print a.square
    print a.value
    ---

    and the result:

    $ python sqval.py
    25
    5.0
    100.0
    10
    64
    8.0
    $

    --
    Regards,
    Wojtek Walczak,
    http://tosh.pl/gminick/
  • Wojtek Walczak at Sep 3, 2008 at 2:34 pm

    On Wed, 3 Sep 2008 14:31:17 +0000 (UTC), Wojtek Walczak wrote:

    class Square(object):
    def __init__(self, val):
    self._square = pow(val, 2)
    self._value = math.sqrt(self.square)
    ^^^^^^^^^^^^^^^^^^^^^^
    or just:
    self._value = val

    :-)


    --
    Regards,
    Wojtek Walczak,
    http://tosh.pl/gminick/
  • Diez B. Roggisch at Sep 3, 2008 at 2:42 pm

    mk schrieb:
    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)

    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?
    Better to make the getter for square return the square of value, and the
    setter of square compute the root & set that. Like this:

    class Squared2(object):

    def __init__(self, value):
    self.value = value


    @apply
    def squared():
    def fset(self, squared):
    self.value = math.sqrt(squared)

    def fget(self):
    return self.value ** 2

    return property(**locals())

    Diez
  • Maric Michaud at Sep 3, 2008 at 2:44 pm

    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
  • Maric Michaud at Sep 3, 2008 at 2:52 pm

    Le Wednesday 03 September 2008 16:44:10 Maric Michaud, vous avez ?crit?:
    ? ? ? ? ?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)
    Oh sorry for this last version the setters should be :

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

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

    as we don't know what is done in _setXXX methods.

    --
    _____________

    Maric Michaud
  • Mk at Sep 3, 2008 at 3:40 pm
    Thanks to everyone for answers..
    *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)
    Thanks for that, I'll keep that in mind.

    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).
    Hmm, why? Is the line of thinking smth like: because the variables
    should be kept to minimum and they should be calculated at the moment
    they are needed?
  • Maric Michaud at Sep 3, 2008 at 4:11 pm

    Le Wednesday 03 September 2008 17:40:43 mk, vous avez ?crit?:
    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).
    Hmm, why? Is the line of thinking smth like: because the variables
    should be kept to minimum and they should be calculated at the moment
    they are needed?
    Because you have to make extra effort to keep the logical relation between
    value and square. self._square is not really needed, and what is not needed
    is just extra hassle.

    Doesn't it clear that your code is more hard to maintain than the
    alternative :

    class Squared(object):

    def __init__(self, val):
    self._val=val

    def fgetvalue(self):
    return self._val
    def fsetvalue(self, val):
    self._val=val
    value = property(fgetvalue, fsetvalue)

    def fgetsquare(self):
    return self.value ** 2
    def fsetsquare(self,s):
    self.value = math.sqrt(s)
    square = property(fgetsquare, fsetsquare)



    --
    _____________

    Maric Michaud
  • Bruno Desthuilliers at Sep 3, 2008 at 5:38 pm

    Maric Michaud a ?crit :
    Le Wednesday 03 September 2008 17:40:43 mk, vous avez ?crit :
    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).
    Hmm, why? Is the line of thinking smth like: because the variables
    should be kept to minimum and they should be calculated at the moment
    they are needed?
    Because you have to make extra effort to keep the logical relation between
    value and square. self._square is not really needed, and what is not needed
    is just extra hassle.

    Doesn't it clear that your code is more hard to maintain than the
    alternative :

    class Squared(object):

    def __init__(self, val):
    self._val=val

    def fgetvalue(self):
    return self._val
    def fsetvalue(self, val):
    self._val=val
    value = property(fgetvalue, fsetvalue)

    def fgetsquare(self):
    return self.value ** 2
    def fsetsquare(self,s):
    self.value = math.sqrt(s)
    square = property(fgetsquare, fsetsquare)
    FWIW, if there's no computation on getting or setting value, you can
    make it a plain attribute.

    But while it's quite clear that in this example use case it would be
    better to have only one property (weither square or value, depending on
    which is the most often use), things are not always that simple in real
    world code, and - as you mentionned - there may be times where you have
    interdependant properties and really want to avoid recomputing the same
    thing over and over. Now there's no one size fits all solution here -
    it's an optimization problem, and as such depends on real use cases.
  • Maric Michaud at Sep 3, 2008 at 11:20 pm

    Le Wednesday 03 September 2008 19:38:13 Bruno Desthuilliers, vous avez ?crit?:
    FWIW, if there's no computation on getting or setting value, you can
    make it a plain attribute.
    Yes, this is the problem with these tiny examples, we don't know at which
    point we must simplify them...
    But while it's quite clear that in this example use case it would be
    better ?to have only one property (weither square or value, depending on
    which is the most often use), things are not always that simple in real
    world code, and - as you mentionned - there may be times where you have
    interdependant properties and really want to avoid recomputing the same
    thing over and over. Now there's no one size fits all solution here -
    it's an optimization problem, and as such depends on real use cases.
    Yes, my advice was exactly in that sense, it's an optimization problem,
    duplicating such a data is a caching mechanism, and should be done knowingly,
    in acceptance of all the complication it comes with.


    --
    _____________

    Maric Michaud
  • Bruno Desthuilliers at Sep 3, 2008 at 2:50 pm

    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):
    self.value=value

    def _fgetvalue(self):
    return self._value
    def _fsetvalue(self, value):
    self._value=value
    self._square=pow(value,2)
    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)

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedSep 3, '08 at 1:57p
activeSep 3, '08 at 11:20p
posts11
users6
websitepython.org

People

Translate

site design / logo © 2022 Grokbase