2013-05-13 3 views
5

Wenn ich eine Liste in einer „allgemeinen“ Art und Weise zu definieren:Listen innerhalb Liste in Python Dereferenzierung

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

und dann versuchen, nur auf das zweite Element der äußeren Liste anhängen:

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

es hängt an alle Elemente der äußeren Liste, wie oben zu sehen ist, wahrscheinlich aufgrund der Tatsache, dass die Elemente Verweise auf die gleiche Liste und nicht verschiedene Listen sind (warum funktioniert es so?). Wie kann ich eine Liste auf dieselbe "generische" Weise erstellen, so dass die inneren Listen unterschiedliche Listen und nicht nur Referenzen sind. Vielen Dank.

Antwort

10

Sie haben Recht, sie sind alle Verweise auf eine Liste.

[[] for _ in range(3)] 

ist eine gängige Methode zum Erstellen einer Liste von unabhängigen leeren Listen. Sie können xrange auf Python 2.x verwenden, aber es wird keinen Unterschied machen, wenn die Länge tatsächlich so klein wie in Ihrem Beispiel ist.

Nicht sicher, wie den Grund erklären hierfür (der Grund ist, dass es auf diese Weise implementiert wird), aber man kann sehen, dass dieses Verhalten (zumindest in passing) dokumentiert here:

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

Das Wort "flach" bedeutet hier genau das: Die Elemente werden durch Referenz kopiert. "Note 2" auf der verknüpften Seite beantwortet auch Ihre Frage.

+1

Eine flache Kopie ist eine gute Wahl. Eine tiefe Kopie zu machen wäre viel komplizierter und teurer. Außerdem wäre es ein einfacher Weg, Singletons zu brechen: '[True] * n' und plötzlich gibt es' n' verschiedene Instanzen von 'True' (oder was auch immer benutzerdefinierter Singleton), die Sie offensichtlich nicht wollen. – Bakuriu

+0

Danke. Sie haben erwähnt, dass ich "Reichweite" verwenden kann, wenn die Länge klein ist? In meinem realen Projekt kann die Länge so groß wie 10000 sein. Kann ich noch "Bereich" verwenden? Ich denke, es würde immer noch funktionieren als Nummer, nicht wahr? – jazzblue

+0

@Gregory es wäre sicher, aber eine Liste von 10000 Nummern würde erstellt und sofort im Prozess gelöscht werden. Das wird wahrscheinlich nicht viel Speicher verbrauchen, ist aber wahrscheinlich etwas langsamer als 'xrange'. Sie können beide Zeit und sehen. –