Условно a + = b «добавляет» b к сохранению результата в a. Это упрощенное описание будет описывать оператор + = во многих языках.
Однако упрощенное описание поднимает пару вопросов.
- Что именно мы подразумеваем под «добавлением»?
- Что именно мы подразумеваем под «сохранением результата в»? Переменные python не хранят значения напрямую, они хранят ссылки на объекты.
В python ответы на оба эти вопроса зависят от типа данных a.
Так что именно означает "добавление"?
- Для чисел это означает добавление чисел.
- Для списков, кортежей, строк и т. Д. Это означает конкатенацию.
Обратите внимание, что для списков + = более гибок, чем +, для оператора + в списке требуется другой список, но оператор + = примет любую итерацию.
Так что же значит "хранить значение в"?
Если объект изменчив, тогда рекомендуется (но не обязательно) выполнять модификацию на месте. Таким образом, точка указывает на тот же объект, что и раньше, но этот объект теперь имеет другое содержимое.
Если объект неизменен, то он, очевидно, не может выполнить модификацию на месте. Некоторые изменяемые объекты могут также не иметь реализации операции добавления на месте. В этом случае переменная «а» будет обновлена, чтобы указывать на новый объект, содержащий результат операции сложения.
Технически это реализуется путем поиска сначала __IADD__
, если это не реализовано, то пробуется __ADD__
и, наконец, __RADD__
.
Требуется осторожность при использовании + = в python для переменных, где мы не уверены в точном типе и, в частности, когда мы не уверены, является ли тип изменчивым или нет. Например, рассмотрим следующий код.
def dostuff(a):
b = a
a += (3,4)
print(repr(a)+' '+repr(b))
dostuff((1,2))
dostuff([1,2])
Когда мы вызываем dostuff с кортежем, кортеж копируется как часть операции + =, поэтому b не изменяется. Однако когда мы вызываем его со списком, список изменяется на месте, поэтому затрагиваются как a, так и b.
В Python 3 подобное поведение наблюдается с типами "bytes" и "bytearray".
Наконец, обратите внимание, что переназначение происходит, даже если объект не заменен. Это не имеет большого значения, если левая часть является просто переменной, но это может вызвать путаницу, когда у вас есть неизменяемая коллекция, ссылающаяся, например, на изменяемые коллекции:
a = ([1,2],[3,4])
a[0] += [5]
В этом случае [5] будет успешно добавлено в список, на который ссылается [0], но затем произойдет исключение, когда код попытается и не сможет переназначить [0].