Reputation: 1136
I am trying to fill the gap in my understanding of Pythons property()
.
Below is the code that I have come up with, to understand property()
:
class Temperature:
def __init__(self, temp = 10):
self.set_temp(temp)
def to_farenheit(self):
return (self._temp * 1.8) + 32
def get_temp(self):
print "getting temperature value"
return self._temp
def set_temp(self, temp):
print "setting temperature value"
if temp < -237:
raise ValueError("this shud be above -273")
else:
self._temp = temp
temps = property(get_temp, set_temp)
I execute the above class and do the following:
>>> t = Temperature()
setting temperature value
>>> t.temps
getting temperature value
10
>>> t.temps = 13
>>> t.temps
13
>>> t.get_temp()
getting temperature value
10
>>>
As you can see above, when I try to set temp
value by assigning t.temps = 13
the set_temp()
function is not getting called which I was expecting would be called because of property()
functionality. Also I am ending up with 2 different values for variable temp
What am I missing?
Upvotes: 3
Views: 83
Reputation: 28893
Use new-style classes which leverages descriptors for properties.
class Temperature(object):
def __init__(self, temp=10):
self.temps = temp
def to_farenheit(self):
return (self._temp * 1.8) + 32
def get_temp(self):
print "getting temperature value"
return self._temp
def set_temp(self, temp):
print "setting temperature value"
if temp < -237:
raise ValueError("this shud be above -273")
else:
self._temp = temp
temps = property(get_temp, set_temp)
This gives you the “right” behavior.
In [30]: t = Temperature()
setting temperature value
In [31]: t.temps
getting temperature value
Out[31]: 10
In [32]: t.temps = 100
setting temperature value
In [33]: t.temps
getting temperature value
Out[33]: 100
In [34]: t.__dict__
Out[34]: {'_temp': 100}
Upvotes: 1
Reputation: 152820
It's simply because you use Python 2 and forgot to subclass object
. In your case property
simply doesn't work because it's an old-style class.
Better you subclass object
:
class Temperature(object):
...
Or even better: Use Python 3. Python 3 doesn't have old-style classes anymore and you can omit the (object)
part because it's implicit.
However you really shouldn't define get_temp
or set_temp
functions when you could use the decorator syntax. And you definitely shouldn't call them directly.
This would be much more pythonic:
class Temperature(object):
def __init__(self, temp = 10):
self.temps = temp
def to_farenheit(self):
return (self._temp * 1.8) + 32
@property
def temps(self):
print("getting temperature value")
return self._temp
@temps.setter
def temps(self, temp):
print("setting temperature value")
if temp < -237:
raise ValueError("this shud be above -273")
else:
self._temp = temp
That example will work on Python 2 and Python 3.
Upvotes: 8
Reputation: 43306
This problem only occurs in python 2.
From the docs:
class property([fget[, fset[, fdel[, doc]]]])
Return a property attribute for new-style classes (classes that derive from object).
(Emphasis mine.)
If you make Temperature
a new-style class by inheriting from object
, the property will work as expected.
Upvotes: 1