[Python 2.7] Przypisywanie list

Hassgesang
Użytkownik
Użytkownik
Posty: 206
Rejestracja: 26 mar 2012, o 20:41
Płeć: Mężczyzna
Lokalizacja: Gdynia
Podziękował: 3 razy
Pomógł: 17 razy

[Python 2.7] Przypisywanie list

Post autor: Hassgesang »

Mamy dwie listy. Chcę skopiować wartości z tej drugiej do pierwszej, jednak nie udaje mi się to.

Kod: Zaznacz cały

X = [0] * 3
for i in range (3):
	X[i] = [0] * 3

print X

A = list(X)
B = X[:]
C = X

A[0][0] = 1
B[0][1] = 2
C[0][2] = 3
X[2][2] = 9

print A, id(A)
print B, id(B)
print C, id(C)
print X, id(X)
Po wykonaniu wszystkie listy zawierają to samo, jest to dla mnie zaskakujące. Jak więc mogę skopiować zawartość między listami? Czy trzeba będzie dopisać drugiego fora?

Kod: Zaznacz cały

[[1, 2, 3], [0, 0, 0], [0, 0, 9]] 139702477064600
[[1, 2, 3], [0, 0, 0], [0, 0, 9]] 139702477065608
[[1, 2, 3], [0, 0, 0], [0, 0, 9]] 139702477021552
[[1, 2, 3], [0, 0, 0], [0, 0, 9]] 139702477021552
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[Python 2.7] Przypisywanie list

Post autor: Afish »

Wszystko jest okej, masz tablicę wielowymiarową, więc jest to lista zawierająca referencje do list - po skopiowaniu masz nowe referencje wskazujące na to samo, czyli de facto płytką kopię listy. Jeżeli chcez mieć głęboką, użyj tego:

Kod: Zaznacz cały

import copy
new_list = copy.deepcopy(old_list)
Hassgesang
Użytkownik
Użytkownik
Posty: 206
Rejestracja: 26 mar 2012, o 20:41
Płeć: Mężczyzna
Lokalizacja: Gdynia
Podziękował: 3 razy
Pomógł: 17 razy

[Python 2.7] Przypisywanie list

Post autor: Hassgesang »

To jest tylko minimalny działający przykład, jest mi to potrzebne do pewnego większego algorytmu. Bliższa analiza wykazała, że tę operację (przepisywania jednej tablicy do drugiej) wykonuję kilka do kilkudziesięciu tysięcy razy, i podane przez Ciebie rozwiązanie jest do trzech, czterech razy wolniejsze niż:

Kod: Zaznacz cały

for var in range (x):
   tab[i] = tab2[i][:]
Nie pozostaje mi nic innego, jak tylko poprawić sam algorytm.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[Python 2.7] Przypisywanie list

Post autor: Afish »

Skoro już walczysz z czasem, to polecam używać xrange zamiast range - jest szybsze, bo nie tworzy całej tablicy w pamięci.
Hassgesang
Użytkownik
Użytkownik
Posty: 206
Rejestracja: 26 mar 2012, o 20:41
Płeć: Mężczyzna
Lokalizacja: Gdynia
Podziękował: 3 razy
Pomógł: 17 razy

[Python 2.7] Przypisywanie list

Post autor: Hassgesang »

Dziękuję za wskazówkę, dopracowanie kopiowania list dało \(\displaystyle{ 15\%}\) (poprawy czasu), zmiana range na xrange tylko \(\displaystyle{ 1\%}\), zaś skrócenie pewnej pętli w algorytmie - ponad \(\displaystyle{ 50\%}\) [wszyskie zyski w pesymistycznym przypadku].

Nie jestem pewien czy zrozumiałem dokumentację - range używam, kiedy potrzebna mi jest lista, zaś xrange jest lepszym wyborem przy pętlach (gdzie nie potrzebuję całej listy, tylko samego licznika przebiegów pętli)?
Awatar użytkownika
Althorion
Użytkownik
Użytkownik
Posty: 4541
Rejestracja: 5 kwie 2009, o 18:54
Płeć: Mężczyzna
Lokalizacja: Wrocław
Podziękował: 9 razy
Pomógł: 662 razy

[Python 2.7] Przypisywanie list

Post autor: Althorion »

range() wygeneruje Ci faktyczną listę, autentycznie istniejący obiekt zawierający wymagane wartości, natomiast xrange() stworzy iterator zwracający kolejne wartości, co jest przede wszystkim bardziej oszczędne pamięciowo.

Nawiasem mówiąc, w Pythonie 3 range() zachowuje się jak xrange(), zaś ten drugi zlikwidowano.
ODPOWIEDZ