Почему значение, добавляемое в список, динамически меняется?

#python #python-3.x #list #dynamic

#питон #python-3.x #Список #динамический

Вопрос:

Версия Python: 3.9.5

Мой Код:

 cells = [[i, i] for i in range(3)] steps = []  for t in range(2):  for i in range(len(cells)):  xrand = random.randint(-5, 5)  yrand = random.randint(-5, 5)  cells[i][0]  = xrand  cells[i][1]  = yrand  steps.append(list(cells))  print(steps)  

Фактический Объем Производства:

 [[[3, 3], [2, 3], [6, 3]]] [[[4, 7], [-3, 2], [8, 3]], [[4, 7], [-3, 2], [8, 3]]]  

Ожидаемый Результат:

 [[[3, 3], [2, 3], [6, 3]]] [[[3, 3], [2, 3], [6, 3]], [[4, 7], [-3, 2], [8, 3]]]  

Я каждый раз меняю значение ячеек списка во внешнем цикле и добавляю измененный список в список шагов. Как вы можете видеть на выходных данных, на второй итерации первый элемент ячеек также изменяется, хотя я только добавляю элемент в список.

Первым элементом шагов является список ячеек из предыдущей итерации. Но на второй итерации оба элемента динамически изменяются, хотя я добавляю только элемент, и поэтому первый элемент не должен быть затронут.

Почему это происходит и как вы это преодолеваете?

Ответ №1:

list(cells) создает неглубокую копию, таким образом, изменение изменяемого содержимого cells также изменит содержимое неглубокой копии — или, скорее, содержимое неглубокой копии на самом деле является тем же объектом, что и содержимое cells .

То, что вам нужно, — это глубокая копия:

 import copy  cells = [[i, i] for i in range(3)] steps = []  for t in range(2):  for i in range(len(cells)):  xrand = 1  yrand = 1  cells[i][0]  = xrand  cells[i][1]  = yrand  steps.append(copy.deepcopy(cells))  print(steps)  

Выход:

 [[[1, 1], [2, 2], [3, 3]]] [[[1, 1], [2, 2], [3, 3]], [[2, 2], [3, 3], [4, 4]]]  

Я заменил random.randint детали статическими значениями, поэтому продемонстрированный результат меньше … Случайный.

Ответ №2:

Списки обрабатываются на месте

Это связано с тем, что список обрабатывается со ссылкой на реальный объект (место хранения) на диске. См. Следующий пример:

 l = [2] x = [l, l] print(x) gt;gt;gt; [[2], [2]] l[0] = 4 print(x) gt;gt;gt; [[4], [4]]  

Вы можете преодолеть это, используя либо новую переменную, либо copy.deepcopy()

 gt;gt;gt; import copy gt;gt;gt; l = [2] gt;gt;gt; x = [copy.deepcopy(l), l] gt;gt;gt; print(x) [[2], [2]] gt;gt;gt; l[0] = 4 gt;gt;gt; print(x) [[2], [4]]