Поведение оператора += с кортежами в Python
@python_quizРазберем этот квиз
Коротко: код

напечатает

Ниже объясню, почему так происходит, покажу демонстрацию с id() и сравню с поведением для изменяемых типов (например, списков).
Разбор кода по шагам
a = b= (1,)
Оба имени, a и b, ссылаются на один и тот же кортеж (1,).
- a += (2,)
Оператор += для кортежей не изменяет существующий кортеж (кортежи неизменяемы). В случае неизменяемого объекта Python фактически выполняет операцию сложения и переназначает имя a на новый объект, равный (1, 2). Имя b продолжает ссылаться на старый кортеж (1,).
- print(a, b)
Выводит два кортежа: новый, связанный с a, и исходный, связанный с b.
Почему так — технически
- Кортежи неизменяемы, у них нет поведения "изменяющегося" результата для +=. При выполнении a += (2,) Python вызывает реализацию in-place (если она есть,
__iadd__), а если её нет или объект неизменяем, использует результат обычного сложения (a = a+ (2,)). В итоге создаётся новый объект и имя a переназначается на него. - Выражение
a = b= (1,) создает один объект и связывает с ним оба имени. Переназначение a не затрагивает b.
Демонстрация с id()
Ниже код показывает, что id(a) изменился, а id(b) остался прежним:

Ожидаемый вывод (id будут числа, разные для нового и старого объектов):

Как видно, id(a) поменялся — создан новый кортеж; id(b) остался тем же — b всё ещё ссылается на исходный кортеж.
Контраст: списки (изменяемый тип)
Для сравнения, со списками поведение другое:

Вывод:

Здесь id не меняется — операция += у списков выполняет добавление элементов "на месте" (метод __iadd__ реализован), поэтому оба имени видят изменённый объект.
Вывод
- Оператор += может либо изменить объект "на месте" (если тип изменяем и реализует
__iadd__), либо создать новый объект и переназначить имя (часто для неизменяемых типов). - Для кортежей a += b фактически создаёт новый кортеж и привязывает его к имени a, в то время как b остаётся ссылаться на исходный кортеж. В результате печать покажет (1, 2) и (1,) соответственно.