我正在学习Python, @property 发生了一件奇怪的事情,我不明白...
我找到了一个有关财产如何运作的示例here,发现这一点很清楚。 以下代码可以正常工作:
class Celsius:
def __init__(self, temperature=0):
self.temperature = temperature
def to_farenheit(self):
return (self.temperature * 1.8) + 32
def get_temperature(self):
print("Getting value") # just to see on screen when we call it
return self._temperature
def set_temperature(self, value):
print("Setting value") # just to see on screen when we call it
if value < -273:
raise ValueError("Temperature cannot be less than -273 °C !")
self._temperature = value
temperature = property(get_temperature, set_temperature)
当我们尝试将温度设置为绝对零以下时,我们看到调用了setter并引发了ValueError:
T = Celsius(-400)
>>> Setting value
>>> Traceback (most recent call last):
>>> ...
>>> ValueError: Temperature cannot be less than -273 °C !
但是,当我们将属性定义为装饰器(即 @property )时,如下代码所示:
class Celsius:
def __init__(self, temperature = 0):
self._temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
@property
def temperature(self):
print("Getting value")
return self._temperature
@temperature.setter
def temperature(self, value):
print("Setting value")
if value < -273:
raise ValueError("Temperature below -273 is not possible")
print("Setting value")
self._temperature = value
我们做同样的事情,不调用setter,也不会引发异常:
T = Celsius(-400)
print(T.temperature)
>>> Getting value
>>> -400
即使我们更改T的值,看起来也从未调用过 @ temperature.setter 。
T = Celsius(20)
print(T.temperature)
>>> Getting value
>>> -400
我不明白...有人可以向我解释吗?
答案 0 :(得分:1)
在类初始化器中,您将输入temperature
设置为实例属性_temperature
,但具有属性temperature
的属性获取器和设置器。
在当前形式下,如果要设置属性temperature
,则会得到所需的异常:
In [505]: c = Celsius(-400)
In [506]: c.temperature
Getting value
Out[506]: -400
In [507]: c.temperature = -500
Setting value
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-507-2b9ed72eeb52> in <module>
----> 1 c.temperature = -500
<ipython-input-504-e44aad21660f> in temperature(self, value)
15 print("Setting value")
16 if value < -273:
---> 17 raise ValueError("Temperature below -273 is not possible")
18 print("Setting value")
19 self._temperature = value
ValueError: Temperature below -273 is not possible
你去了。
现在,如果将__init__
更改为将输入temperature
设置为temperature
属性,则在初始化类时会得到异常:
In [508]: class Celsius:
...: def __init__(self, temperature = 0):
...: self.temperature = temperature
...:
...: def to_fahrenheit(self):
...: return (self.temperature * 1.8) + 32
...:
...: @property
...: def temperature(self):
...: print("Getting value")
...: return self.temperature
...:
...: @temperature.setter
...: def temperature(self, value):
...: print("Setting value")
...: if value < -273:
...: raise ValueError("Temperature below -273 is not possible")
...: print("Setting value")
...: self.temperature = value
...:
In [509]: c = Celsius(-400)
Setting value
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-509-1fc014754084> in <module>
----> 1 c = Celsius(-400)
<ipython-input-508-af8466917803> in __init__(self, temperature)
1 class Celsius:
2 def __init__(self, temperature = 0):
----> 3 self.temperature = temperature
4
5 def to_fahrenheit(self):
<ipython-input-508-af8466917803> in temperature(self, value)
15 print("Setting value")
16 if value < -273:
---> 17 raise ValueError("Temperature below -273 is not possible")
18 print("Setting value")
19 self.temperature = value
ValueError: Temperature below -273 is not possible
为什么您的第一个代码有效?
在第一个代码中,您已将属性temperature
设置为temperature
中的输入__init__
。
由于使用了property
可调用(它是一个描述符),python看到您有一个描述符temperature
,同时它也是一个数据描述符,同时还有一个setter。因此,它尝试调用setter方法来设置值。