Каждое имя переменной в Python следует рассматривать как ссылку на часть данных.В вашем первом листинге b
содержит две ссылки на один и тот же базовый объект, на который также ссылается имя a
.Этот объект изменяется на месте с помощью операций, которые вы используете для вращения его членов.Эффект этого изменения виден, когда вы смотрите на или из двух ссылок на объект, найденный в b
, или действительно, когда вы смотрите на ссылку, связанную с именем a
.
Их идентичность можно увидеть с помощью функции id()
: id(a)
, id(b[0])
и id(b[1])
все возвращают одно и то же число, которое является уникальным идентификатором базового объекта списка, на который они все ссылаютсяк.Или вы можете использовать оператор is
: b[0] is b[1]
оценивается как True
.
Напротив, во втором листинге вы переназначаете a
- другими словами, используя оператор присваивания =
, вы связываете это имя с другим объектом:в этом случае новый list
объект, который вы только что создали с помощью литерального выражения в квадратных скобках.b
по-прежнему содержит одну ссылку на старый список, и теперь вы добавляете новую ссылку, которая указывает на эту другую часть базовых данных.Таким образом, два элемента b
теперь выглядят отличными друг от друга - и действительно, они являются разными объектами и, соответственно, имеют разные id()
числа, только один из которых совпадает с текущим id(a)
.b[0] is b[1]
теперь оценивается как False
Как это исправить?Переназначите имя a
перед его изменением: например, создайте копию:
a = list(a)
или:
import copy
a = copy.copy(a)
(или вы можете даже использовать copy.deepcopy()
- изучить разницу).В качестве альтернативы, поверните элементы a
, используя методы, которые влекут за собой переназначение, а не изменения на месте - например:
a = a[1:] + a[:1]
(NB неизменяемые объекты, такие как tuple
, избегают всего этогопутаница - не потому, что они ведут себя принципиально иначе, а потому, что у них нет методов, которые производят изменения на месте и поэтому вынуждают вас использовать стратегии переназначения.)