2015-12-21 20 views
5

Jestem stary i nie mam już włosów do wyciągnięcia. Czytałem tyle odpowiedzi na podobne pytania, jakie mogę znaleźć na SO. Mam następujący kod:Zrozumienie listy Pythona 3.5 modyfikuje oryginał

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)` 

wyjściowa wynosi:

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']] 

szukam wyniku przedstawionego jako „C po:” ale ja nie rozumiem, dlaczego jest modyfikowany, zbyt ?! Próbowałem też

c = list(a) 

i

c = copy.copy(a) 

Oczywiście, proste c = a nie działa zgodnie z oczekiwaniami. Czego mi brakuje ?! Dziękuję.

Odpowiedz

7

Dzieje się tak dlatego, że nie kopiuje się elementów na liście. Listy wewnątrz a nie są kopiowane. Dlatego twoja metoda extend wpływa na elementy wewnątrz obu list. Powinieneś użyć c = copy.deepcopy(a), aby skopiować zagnieżdżone elementy.

1

próba przypisania C Wykaz takiego (bez .copy() roztwór)

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

lub jedna wkładka z listowego

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

ten dostarcza głęboki kopię, jeśli masz listę wewnątrz listy , nie 3 warstwy oczywiście.

Przyczyną niepowodzenia jest prawidłowe skopiowanie listy, ale listy wewnątrz wciąż mają tę samą wartość pamięci, dlatego nie było kopii na liście elementów. To rozwiązanie kopiuje również wewnętrzne listy: , która jest definicją deepcopy.

0

Jak wyjaśniono na innych plakatach, listy wewnątrz A nie są w rzeczywistości kopiowane do C - to tylko odniesienia do oryginalnych. Widać, że po uruchomieniu poniższy kod:

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) 

która drukuje „True”, co oznacza, że ​​[1,2] wewnątrz lists_copy jest w rzeczywistości [1,2] z num_lists. Kopiowanie list w Pythonie jest zbyt skomplikowane i mam nadzieję, że zmienią je na bardziej przyjazne w przyszłości. Jak na razie, to najlepsze co możesz zrobić, to: lists_copy = copy.deepcopy(num_lists)

Widać to działa poniżej:

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) 

ten kod wydruki „false”, co oznacza, że ​​lista jest bezpiecznie kopiowane i równowaga jest ostatecznie przywrócony do wszechświat:)

0

Należy również pamiętać, że listy są zmiennymi, które można modyfikować po utworzeniu w przeciwieństwie do niezmiennych typów, takich jak na przykład łańcuchy. Typów niezmiennych nie można zmienić po ich utworzeniu. Dlatego tworzona jest prawdziwa kopia napisu, jeśli spróbujesz do niego dodać drugi ciąg. Zmienione typy można zmienić. Dlatego też nie jest wykonywana żadna kopia, a zarówno a, jak i c odnoszą się do tej samej listy.