Понимание списка Python 3.5 изменяет исходный

Я стар и не имею волос, чтобы вытащить. Я прочитал так много ответов на подобные вопросы, которые я могу найти на SO. У меня есть следующий код:

a = [[1,2],[3,4],[4,5]] b = ['a','b','c'] print('a:',a) print('b:',b) c = a[:] print('c == a:', c==a) print('c is a:',c is a) print('id(c) = id(a):', id(c)==id(a)) [x.extend(b) for x in c] print('c after:',c) print('a after:',a)` 

Выход:

 a: [[1, 2], [3, 4], [4, 5]] b: ['a', 'b', 'c'] c == a: True c is a: False id(c) = id(a): False c after: [[1, 2, 'a', 'b', 'c'], [3, 4, 'a', 'b', 'c'], [4, 5, 'a', 'b', 'c']] a after: [[1, 2, 'a', 'b', 'c'], [3, 4, 'a', 'b', 'c'], [4, 5, 'a', 'b', 'c']] 

Я ищу результат, показанный как «c after:», но я не понимаю, почему это тоже изменено ?! Я также пробовал

 c = list(a) 

а также

 c = copy.copy(a) 

Конечно, простой c = a работает не так, как ожидалось. Что мне не хватает ?! Спасибо.

Это происходит потому, что вы не копируете элементы внутри списка. Списки внутри a не копируются. Поэтому ваш метод extend влияет на элементы внутри обоих списков. Вы должны использовать c = copy.deepcopy(a) , чтобы скопировать вложенные элементы.

попробуйте назначить c-список следующим образом (без .copy ())

 c = [] for elem in a: c.append(list(elem)) 

или один вкладыш со списком

 c = [list(elem) for elem in a] 

Это обеспечивает глубокую копию, если у вас есть список внутри списка, а не 3 слоя, конечно.

Причина, по которой вы потерпели неудачу, – это то, что вам удалось скопировать список должным образом, но списки внутри по-прежнему привязаны к одному и тому же значению памяти, поэтому в списках элементов не было копии. Это решение также копирует внутри списков, что является определением deepcopy.

Как пояснили другие плакаты, списки внутри A на самом деле не скопированы на C – они просто ссылки на оригинальные. Вы можете видеть, что при запуске кода ниже:

 num_lists = [[1,2],[3,4],[4,5]] lists_copy = num_lists[:] orig_first = num_lists[0] copy_first = lists_copy[0] print('Are the first elements the same object?', orig_first is copy_first) 

Что печатает «True», что означает, что [1,2] внутри lists_copy на самом деле является [1,2] из num_lists. Копирование списков Python слишком сложное, и я надеюсь, что они изменят его, чтобы быть более дружелюбным в будущем. На данный момент лучшее, что вы можете сделать, это: lists_copy = copy.deepcopy(num_lists)

Вы можете видеть, как это работает ниже:

 from copy import deepcopy lists_copy = deepcopy(num_lists) orig_first = num_lists[0] copy_first = lists_copy[0] print('Are they they the same after copying with deepcopy?', orig_first is copy_first) 

Этот код печатает «False», что означает, что список безопасно скопирован, и баланс, наконец, восстановлен во вселенной:)

Учитывайте также, что списки являются изменяемыми типами, которые могут быть изменены после создания в отличие от неизменяемых типов, таких как строки, например. Неизменяемые типы не могут быть изменены после их создания. Поэтому реальная копия строки создается, если вы попытаетесь добавить к ней вторую строку. Изменчивые типы могут быть изменены. Следовательно, копия не производится, и как a, так и c ссылаются на один и тот же список.