顺序:
>>> a=Celsius()
>>> a.temperature = [7,8]
setting temperature
>>> a.temperature[0] = 0
getting value
特别有趣,因为您授予了对_temperature 列表的访问权限,而邪恶的用户可能会破坏您的Celsius 实例。有人想要这样的东西:
>>> a=Celsius()
>>> a.temperature = [7,8]
setting temperature (I CHECK THAT THOSE VALUES ARE CONSISTENT)
>>> a.temperature[0] = 0
setting ONE temperature (I CHECK THAT THIS VALUE IS CONSISTENT)
基本上,您失去了对对象的控制,因为您无法检查邪恶用户可以做什么。这似乎是一个危险的设计。这里有一个建议:永远不要与外部世界共享可变对象,始终提供不可变对象或副本。(这确保符合Law of Demeter)。替换:
@property
def temperature(self):
print("getting value")
return self._temperature
作者:
@property
def temperature(self):
print("getting value")
return list(self._temperature)
然后试试你的测试用例:
>>> a=Celsius()
>>> a.temperature = [7,8]
setting temperature (I CHECK THAT THOSE VALUES ARE CONSISTENT)
>>> a.temperature[0] = 0
getting value
>>> a.temperature
getting value
[7, 8] # NO MODIFICATION HERE
现在您的 Celsius 对象受到保护,不会被随意修改:如果您想更改 _temperature 列表,您必须提供一个完整的列表,setter 应该检查该列表。
如果您想更改单个值,这仍然是可能的,但是会调用 setter(以及可能的检查):
>>> a=Celsius()
>>> a.temperature = [7,8]
setting temperature (I CHECK THAT THOSE VALUES ARE CONSISTENT)
>>> new_temp = [0] + a.temperature[1:]
getting value
>>> a.temperature = new_temp
setting temperature (I CHECK THAT THOSE VALUES ARE CONSISTENT)
>>> a.temperature
getting value
[0, 8]
如果你绝对希望用户通过索引设置一个项目,你必须手动编写一个函数:
class Celsius:
...
def set_temperature_item(self, i, v):
print ("setting ONE temperature (I CHECK THAT THIS VALUE IS CONSISTENT)")
self._temperature[i] = v
>>> a=Celsius()
>>> a.temperature = [7,8]
setting temperature (I CHECK THAT THOSE VALUES ARE CONSISTENT)
>>> a.set_temperature_item(0, 0)
setting ONE temperature (I CHECK THAT THIS VALUE IS CONSISTENT)
>>> a.temperature
getting value
[0, 8]
物业
我认为你不能用property 这样做,因为当你写的时候:
a.temperature[0] = 0
相当于:
a.__getattribute__("temperature").__setitem__(0, 0)
而且您无法决定 __getattribute__ 调用接下来会发生什么:只需获取值或使用它来设置项目。