2014-01-02 3 views
2

Я строю список списков. Я читаю элементы из входного файла. Я читаю в каждой строке в файле как строку-одиночный элемент в под-список в списке. Во-первых, я создал список списков:Почему «append» мутирует все элементы в списке?

>>> b = [[]] * 5 

Однако, когда я попытался добавить элемент, я получил следующее:

>>> b[1].append("abc") 
>>> b 
[ ['abc'], ['abc'], ['abc'], ['abc'], ['abc']) 

Почему append изменения все вложенные списки? insert() лучше в этой ситуации?

+0

проблема является [[]] * 5 - посмотреть, что происходит с этим Ь = [[], [], [], [], []] – user3125280

+0

посмотреть здесь HTTP : //stackoverflow.com/questions/6688223/python-list-multiplication-3-makes-3-lists-which-mirror-each-other-when – corn3lius

ответ

7

Когда вы делаете [[]] * 5, это список из тех же предметов (пустые списки здесь), повторяющиеся 5 раз.

Вы можете проверить это:

>>> b = [[]] *5 

>>> b 
[[], [], [], [], []] 

>>> id(b[0]) 
140588316211896 

>>> id(b[1]) 
140588316211896 

Что вы должны сделать, это:

>>> b = [[] for i in range(5)] 
>>> b[0].append('abc') 
>>> b 
[['abc'], [], [], [], []] 

В случае [[] for i in range(5)], в каждом цикле создается новый пустой объект списка.

И вставка не будет хорошим вариантом здесь, потому что вставка - это операция O(n), тогда как добавление будет O(1).

+0

Не могли бы вы объяснить, почему ваше решение работает, почему в вашей жизни списки не являются одним и тем же объектом? – idish

+0

@idish: Потому что в каждом цикле создается новый пустой объект списка. –

+0

@ Ankur Как вы знаете, что insert() - это O (n) и append O (1)? – Dombey

1

Когда вы говорите

b = [[]] * 5 

Это создает 5 списков, которые указывают на то же самое. Если вы распечатаете адрес каждого элемента, вы обнаружите, что они одинаковы.

Не имеет значения, использовали ли вы append или insert.

+0

No. Под капотом список состоит в основном из 5 ссылок на тот же уникальный список '' [] '', это не означает, что список указывает на «вещь». Вещь ? Для этого есть слово, это «объект». – eyquem

+0

@eyquem Да, было бы неточно сказать, что это список списков, но я действительно не вижу большой разницы между ссылкой на него как на «вещь» или «объект». – MxyL

0

Это FAQ. Все 5 элементов списка верхнего уровня указывают на один список.

Проверьте это:

#!/usr/local/cpython-3.3/bin/python 

if True: 
    b = [[] for dummy in range(5)] 
else: 
    b = [[]] * 5 

b[1].append("abc") 

print(b) 
Смежные вопросы