Так что я столкнулся с этой неприятной ошибкой сегодня в своем коде. Я только недавно использовал свойства Python и использовал его для сохранения старого значения свойства в другой переменной всякий раз, когда свойство было обновлено. Поэтому, когда вызывается функция setter, мне нужно сохранить старое значение, а затем новое значение для передачи.Это ошибка? Свойство Python работает некорректно с + =
Оказывается, при использовании +=
на свойстве вызывается метод __iadd__
, обновляющий свойство на месте, затем вызывается сеттер. Но к тому времени старое значение теряется. Вот несколько примеров, иллюстрирующих проблему.
class Container(object):
def __init__(self, val):
self.val = val
def __add__(self, other):
print('in __add__', other)
return Container(self.val + other.val)
def __iadd__(self, other):
print('in __iadd__:', other)
self.val += other.val
return self
def __str__(self):
return str(self.val)
class Test:
def __init__(self):
self._val = Container(0)
@property
def val(self):
return self._val
@val.setter
def val(self, values):
print("changing from {} to {}".format(self._val, values))
self._val = values
test = Test()
print('val=', test.val)
test.val = Container(2)
print('val=', test.val)
test.val = test.val + Container(1)
print('val=', test.val)
test.val += Container(1)
print('val=', test.val)
test.val.__iadd__(Container(1))
print('val=', test.val)
При запуске он дает этот результат:
val= 0
changing from 0 to 2
val= 2
in __add__ 1
changing from 2 to 3
val= 3
in __iadd__: 1
changing from 4 to 4
val= 4
in __iadd__: 1
val= 5
Он говорит, что это меняется от 4 до 4, но она действительно меняется от 3 до 4, и что было пропущено. Так что мне интересно, если это ошибка, я что-то упустил, или просто не должен использовать + =, если я имею дело с свойством и нуждаюсь в старом значении.
Вы можете проверить http://stackoverflow.com/questions/11987949/how-to-implement-iadd-for-a -python-property – Jan
Это почти помогло. Если бы я просто заменил '__iadd__' на' __add__' на объектах, тогда он исправит его. Но только моя удача '__Iadd__' является атрибутом ready-only для массивов numpy. Поэтому я просто избавился от сеттера и сделал его функцией несобственного набора. – TheLoneMilkMan