properties setting each other

M

mk

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:

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)


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?
 
D

Diez B. Roggisch

mk said:
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:


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)



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
 
B

Bruno Desthuilliers

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:
>

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)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,043
Latest member
CannalabsCBDReview

Latest Threads

Top