2013-05-13 11 views
5

Kiedy zdefiniować listę w "rodzajowe" sposób:dereferencing list listy wewnątrz w Pythonie

>>>a=[[]]*3 
>>>a 
[[],[],[]] 

a następnie spróbować dołączyć tylko do drugiego elementu listy zewnętrzna:

>>>a[1].append([0,1]) 
>>>a 
[[[0,1]], [[0,1]], [[0,1]]] 

dołącza się do wszystkich elementów z zewnętrznej listy, jak widać powyżej, prawdopodobnie ze względu na to, że elementy są odniesieniami do tej samej listy, a nie różnymi listami (dlaczego to działa w ten sposób?). W jaki sposób mogę faktycznie utworzyć listę w ten sam "ogólny" sposób, tak że wewnętrzne listy byłyby różnymi listami, a nie tylko referencjami. Dzięki.

Odpowiedz

10

Masz rację, wszystkie są odniesieniami do jednej listy.

[[] for _ in range(3)] 

to popularny sposób tworzenia listy niezależnych pustych list. Możesz użyć xrange na Pythonie 2.x, ale nie będzie to miało znaczenia, jeśli długość jest rzeczywiście tak mała, jak w twoim przykładzie.

Nie wiem, jak to wytłumaczyć powód do tego (to dlatego, że jest to realizowane w ten sposób), ale widać, że takie zachowanie jest udokumentowana (przynajmniej mimochodem) here:

Operation  Result        Notes 
s * n, n * s n shallow copies of s concatenated (2) 

Słowo "płytkie" oznacza tutaj dokładnie: elementy są kopiowane przez odniesienie. "Uwaga 2" na połączonej stronie również odpowiada na twoje pytanie.

+1

Wykonanie płytkiej kopii jest dobrym wyborem. Wykonanie głębokiej kopii byłoby znacznie bardziej skomplikowane i kosztowne. Byłby to także łatwy sposób na złamanie singletonów: '[True] * n' i nagle są różne n 'instancji' True' (lub jakiegokolwiek zdefiniowanego przez użytkownika singleton), którego oczywiście nie chcesz. – Bakuriu

+0

Dzięki. Wspomniałeś, że mogę użyć "zakresu", jeśli długość jest mała? W moim prawdziwym projekcie długość może wynosić nawet 10000. Czy nadal mogę używać "zasięgu"? Myślę, że nadal by działało na więcej niż numer, prawda? – jazzblue

+0

@Gregory to na pewno, ale lista 10000 numerów zostanie utworzona i natychmiast usunięta w procesie. To prawdopodobnie nie zje dużo pamięci, ale prawdopodobnie będzie nieco wolniej niż "xrange". Możesz czas obie i zobaczyć. –