2011-01-03 16 views
5

Myślałem, że znam Pythona do dziś wieczorem. Jaki jest właściwy sposób na zrobienie czegoś takiego? Oto mój kod:Mylące obiekty Pythona: a = b, modyfikuj b i zmiany!

a = ["one", "two", "three"] 
b = a # here I want a complete copy that when b is changed, has absolutely no effect on a 
b.append["four"] 
print a # a now has "four" in it 

Zasadniczo chcę wiedzieć, zamiast kroku b = a, jak bym prawidłowo wykonać kopię listy lub słownika tak, że kiedy b ulega zmianie a nie zmienia się wraz z nim?

+5

Cóż, nie znasz Pythona. A przynajmniej nie znasz ważnej części tego, jakie są zmienne. Zobacz podobne pytanie na SO lub np. http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables. – delnan

+5

@delnan, aby być uczciwym, nie jest to niecodzienna pułapka dla ludzi, którzy są nowicjuszami w pythonach, aby zrozumieć, że przypisanie zmiennych z listami przypisuje referencje, chociaż twierdzenie "Myślałem, że znam Pythona" ma tendencję do wskazywania, że ​​nie są one "nowe":) –

Odpowiedz

11

To, czego doświadczasz, to pojęcie referencji. Wszystkie obiekty w Pythonie mają odniesienie i jeśli przypiszesz jedną do dwóch nazw a i b, spowoduje to, że zarówno a, jak i b będą wskazywały na ten sam obiekt .

>>> a = range(3) 
>>> b = a      # same object 
>>> b.append(3) 
>>> a, b      # same contents 
([0, 1, 2, 3], [0, 1, 2, 3]) 

listach możesz utworzyć nową listę b który jest skopiować innego a użyciu b = a[:].

>>> a = range(3) 
>>> b = a[:]     # make b a new copy of a 
>>> b.append(3) 
>>> a, b      # a is left unchanged 
([0, 1, 2], [0, 1, 2, 3]) 

Aby uzyskać bardziej ogólne rozwiązanie dla dowolnego obiektu, należy użyć copy module. Płytka kopia skopiuje odniesienia przechowywane w kopiowanym obiekcie, podczas gdy głęboka kopia rekurencyjnie utworzy nowe kopie wszystkich obiektów.

>>> a = [range(2), range(3)] 
>>> b = copy.copy(a)   # shallow copy of a, equivalent to a[:] 
>>> b[0] = range(4) 
>>> a, b      # setting an element of b leaves a unchanged 
([[0, 1], [0, 1, 2]], [[0, 1, 2, 3], [0, 1, 2]]) 
>>> b[1].append(3) 
>>> a, b      # modifying an element of b modifies the element in a 
([[0, 1], [0, 1, 2, 3]], [[0, 1, 2, 3], [0, 1, 2, 3]]) 

>>> a = [range(2), range(3)] 
>>> b = copy.deepcopy(a)  # deep recursive copy of a 
>>> b[1].append(3) 
>>> a, b      # modifying anything in b leaves a unchanged 
([[0, 1], [0, 1, 2]], [[0, 1], [0, 1, 2, 3]]) 
+0

jaka jest głęboka kopia i jaka jest płytka kopia. zauważyłem, że ciąg dict.copy .__ doc__ mówi o "płytkiej" kopii. co za różnica? – james

+5

Sprawdź http: // stackoverflow.com/questions/184710/what-is-the-the-between-a-deep-copy-and-shallow-copy – Sapph

+0

To właściwie płytka kopia, ale poza tym właściwy sposób na skopiowanie listy. – Keith

1

Prawidłowy sposób kopiowaniu obiektu jest

from copy import copy 
a = [1, 2, 3] 
b = copy(a) 

Całkiem proste. Jest skróty dla list:

a = [1, 2, 3] 
b = a[:] 

Istnieje również deepcopy(), jeśli chcesz skopiować obiekty w listy również.

+0

Uważaj na nadużycie głębokości. Może to spowodować eksplozję użycia pamięci i czasami daje dziwne błędy "obiektu, który nie daje się wylizać". Prawie we wszystkich przypadkach nie potrzebujesz * kopii, a w innych przypadkach zrobi to płytka kopia. – bukzor

1

Oto 3 sposoby, aby wykonać kopię listy a:

notacja Zastosowanie slice:

copy_of_a = a[:] 

użyć konstruktora listy:

copy_of_a = list(a) 

użyć modułu kopiowania:

from copy import copy 
copy_of_a = copy(a) 

To są płytkie kopie, które wystarczą na twoje pytanie. Aby dowiedzieć się o różnicy między płytką kopią i głęboką kopią przeczytaj documentation of the copy module.

Powiązane problemy