Ответ 1
Да, он ожидал.
Кортеж не может быть изменен. Кортеж, как и список, представляет собой структуру, которая указывает на другие объекты. Он не заботится о том, что эти объекты. Они могут быть строками, числами, кортежами, списками или другими объектами.
Так что делайте что-либо одному из объектов, содержащихся в кортеже, включая добавление к этому объекту, если это список, не относится к семантике кортежа.
(Представьте, если вы написали класс, на котором были методы, из-за которых его внутреннее состояние изменилось. Вы не ожидали, что невозможно будет вызвать эти методы для объекта на основе того, где он хранится).
Или другой пример:
>>> l1 = [1, 2, 3]
>>> l2 = [4, 5, 6]
>>> t = (l1, l2)
>>> l3 = [l1, l2]
>>> l3[1].append(7)
Два изменяемых списка, на которые ссылается список и кортеж. Должна ли я выполнить последнюю строку (ответ: да). Если вы думаете, что ответ нет, почему бы и нет? Если t
изменить семантику l3
(ответ: нет).
Если вы хотите неизменный объект последовательных структур, он должен быть кортежами до конца.
Почему это ошибка?
В этом примере используется оператор infix:
Многие операции имеют "на месте" версию. Следующие функции обеспечивают более примитивный доступ к операторам на месте, чем обычные синтаксис does; например, утверждение x + = y эквивалентно x = operator.iadd(x, y). Другой способ сказать, что z = оператор .iadd(x, y) эквивалентен составному утверждению z = x; Z + = y.
https://docs.python.org/2/library/operator.html
Итак, это:
l = [1, 2, 3]
tup = (l,)
tup[0] += (4,5,6)
эквивалентно этому:
l = [1, 2, 3]
tup = (l,)
x = tup[0]
x = x.__iadd__([4, 5, 6]) # like extend, but returns x instead of None
tup[0] = x
Линия __iadd__
преуспевает и изменяет первый список. Таким образом, список был изменен. Вызов __iadd__
возвращает измененный список.
Вторая строка пытается назначить список кортежу, и это не удается.
Итак, в конце программы список был расширен, но вторая часть операции +=
не удалась. Подробные сведения см. В этом вопросе.