Последовательность:
>>> 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)
По сути, вы потеряли контроль над своим объектом, потому что вы не можете проверить, что может сделать злой пользователь. Это кажется опасным дизайном. Вот предложение: никогда не делитесь изменяемым объектом с внешним миром, всегда предоставляйте неизменный объект или копию. (Это обеспечивает соблюдение Закона Деметры ). Заменить:
@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
, вы должны предоставить полный список, который должен быть проверен установщиком.
Если вы хотите изменить одно значение, это все еще возможно, но есть вызов к установщику (и возможная проверка):
>>> 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__
, что будет дальше: просто получите значение или используйте его для установки элемента.