Общий ответ: +=
пытается вызвать специальный метод __iadd__
, а если он недоступен, он пытается использовать __add__
. Таким образом, проблема заключается в различии между этими специальными методами.
Специальный метод __iadd__
предназначен для дополнения на месте, то есть он мутирует объект, на котором он действует. Специальный метод __add__
возвращает новый объект и также используется для стандартного оператора +
.
Поэтому, когда оператор +=
используется для объекта, у которого __iadd__
определен объект изменен на месте. В противном случае вместо этого попытается использовать plain __add__
и вернуть новый объект.
Вот почему для изменяемых типов, таких как списки +=
, изменяется значение объекта, тогда как для неизменяемых типов, таких как кортежи, строки и целые числа вместо этого возвращаются новый объект (a += b
становится эквивалентным a = a + b
).
Для типов, которые поддерживают как __iadd__
, так и __add__
, вы должны быть осторожны, какой из них вы используете. a += b
вызывается __iadd__
и мутирует a
, тогда как a = a + b
создаст новый объект и назначит его a
. Это не то же самое действие!
>>> a1 = a2 = [1, 2]
>>> b1 = b2 = [1, 2]
>>> a1 += [3] # Uses __iadd__, modifies a1 in-place
>>> b1 = b1 + [3] # Uses __add__, creates new list, assigns it to b1
>>> a2
[1, 2, 3] # a1 and a2 are still the same list
>>> b2
[1, 2] # whereas only b1 was changed
Для неизменяемых типов (где у вас нет __iadd__
) a += b
и a = a + b
эквивалентны. Это позволяет использовать +=
для неизменяемых типов, что может показаться странным конструктивным решением, пока вы не подумаете, что в противном случае вы не могли бы использовать +=
для неизменяемых типов, таких как числа!
Вы действительно используете свойство results
(например, в вашем шаблоне)? Вычисленные свойства не пересчитываются, если они не используются.
В отличие от того, что говорит @match, я сомневаюсь, что у вас есть проблема реактивности, поскольку вы не добавляете и не удаляете свойства (они уже существуют в ваших данных, поэтому они уже реагируют).