当 属性 用作装饰器时, setter 不会引发异常
When property is used as decorator, the setter does not raise the exception
我正在学习 Python,@属性 发生了一件奇怪的事情,我不明白...
我找到了一个关于 属性 如何工作的示例 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 !
然而,当我们将属性定义为装饰器时(即@属性),如下面的代码:
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
看起来 @temperature.setter 从未被调用过,即使我们改变了 T 的值:
T = Celsius(20)
print(T.temperature)
>>> Getting value
>>> -400
我不明白...有人可以给我解释一下吗?
在您的 class 启动器中,您将输入 temperature
设置为实例属性 _temperature
,但是您有 属性 getter 和 setter对于属性 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
属性,则在初始化 class:
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
设置为 __init__
中的输入 temperature
值。
由于使用了 property
可调用(它是一个描述符),python 看到你有一个描述符 temperature
并且它是一个数据描述符,因为你有一个 setter 还有。因此它尝试调用 setter 方法来设置值。
我正在学习 Python,@属性 发生了一件奇怪的事情,我不明白...
我找到了一个关于 属性 如何工作的示例 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 !
然而,当我们将属性定义为装饰器时(即@属性),如下面的代码:
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
看起来 @temperature.setter 从未被调用过,即使我们改变了 T 的值:
T = Celsius(20)
print(T.temperature)
>>> Getting value
>>> -400
我不明白...有人可以给我解释一下吗?
在您的 class 启动器中,您将输入 temperature
设置为实例属性 _temperature
,但是您有 属性 getter 和 setter对于属性 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
属性,则在初始化 class:
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
设置为 __init__
中的输入 temperature
值。
由于使用了 property
可调用(它是一个描述符),python 看到你有一个描述符 temperature
并且它是一个数据描述符,因为你有一个 setter 还有。因此它尝试调用 setter 方法来设置值。