2010-03-24 13 views
12

ich eine Liste haben, sagen wir mal, a = [[1,2],[3,4],[5,6]]Anfügen Artikel zu Listen in einer Liste Verständnis

ich die Zeichenfolge 'a' zu jedem Eintrag in der Liste a hinzufügen möchten.

Wenn ich:

a = [x.append('a') for x in a] 

kehrt [None,None,None].

Aber wenn ich benutze:

a1 = [x.append('a') for x in a] 

dann tut es etwas seltsam.

a, aber nicht a1 ist [[1,2,'a'],[3,4,'a'],[5,6,'a']].

Ich verstehe nicht, warum der erste Anruf [None, None, None] noch warum die zweite auf a statt a1 zurückgibt.

Antwort

7

Für den ersten Fall ist der Grund, warum es [None, None, None] zurückgibt, weil die list.append Funktion None zurückgibt, und das ist, was es in der Liste speichert.

Im zweiten Fall ist es, weil die Liste wandelbar ist, und jedes Mal, wenn Sie den Wert anhängen, wird die ursprüngliche Liste geändert.

Was Sie brauchen, ist ein Nicht-An-Ort-Append-Operator wie +. d.h. [x + ['a'] for x in a].

23

list.append mutiert die Liste selbst und gibt None. Listenkomprehensionen sind für das Ergebnis zu speichern, das ist nicht das, was Sie in diesem Fall wollen, wenn Sie wollen einfach nur die ursprünglichen Listen ändern.

>>> x = [[1, 2], [3, 4], [5, 6]] 
>>> for sublist in x: 
...  sublist.append('a') 
... 
>>> x 
[[1, 2, 'a'], [3, 4, 'a'], [5, 6, 'a']] 
3

(Dies ist eine Kombination der Antworten von Mike Graham und sykora):

Wenn Sie nur die Werte an Ort und Stelle ändern möchten, versuchen, eine regelmäßige for-Schleife, und nicht eine Liste Verständnis :

for sublist in a: 
    sublist.append('a') 

Wenn Sie einen in Ruhe lassen wollen, und das Ergebnis in a1 setzen:

a1 = [sublist + ['a'] for sublist in a] 

Als sie erklärt, append die Liste ändert, gibt aber keine, während + die Liste allein lässt, sondern eine neue, den beigefügten Liste zurückgibt.

+3

Das sollte a1 sein = [Unterliste + ['a'] für Unterliste in a]. Beachten Sie die Klammern um 'a'. –

+0

Whoops. Fest. Vielen Dank. – Oddthinking

0

verlassen die a = und die Nebenwirkung auf a verwenden:

[x.append('a') for x in a] 
print a 
+2

Bitte, nein. Ein Listenverständnis wegzuwerfen, nur um seine Nebenwirkungen zu nutzen, ist schlechte Form; Ihr Vorschlag funktioniert, aber es ist verpönt, genauso wie eine ähnliche Map-Nutzung verpönt ist. Explizit ist besser als implizit; Verwenden Sie eher eine Schleife als ein Listenverständnis. – tzot

6

Wie andere gesagt haben, append mutiert die Liste selbst und Sie sollten es nicht zu einer Variablen zuweisen. Ausführen es ihm die Daten ändert, effektiv jede Aktualisierung auf dem Gerät gerichtet.

Aber, gibt es einen Trick, den ich benutze, wenn ich Sachen in einer funktionalen * Art und Weise tun will, während bestehende Objekte mutiert (anstatt neue zu konstruieren, in diesem Fall mit a=[x + ['a'] for x in a] oder speziell den x + ['a']).

Also, wenn Sie mutig genug sind, können Sie auch dies tun:

>>> a=[[1,2],[3,4],[5,6]] 
>>> a=[x.append('a') or x for x in a] 
>>> a 
[[1, 2, 'a'], [3, 4, 'a'], [5, 6, 'a']] 

Das funktioniert, weil append kehrt None und die or auf weiter für eine Wahrheit-y-Wert zu suchen, die xist (es ist ein list mit mindestens was wurde angehängt).

Warum brauche ich das überhaupt?

Sagen Sie eine Liste haben, und Sie wollen einige seiner Mitglieder zu einer neuen Liste einfügen, und die Referenzen entsprechend aktualisieren:

So sehen Sie die Liste haben all:

>>> all = [[], [], [], []] 

Einige sie eingeführt und aktualisiert, um eine neue Liste x:

>>> x = [i.append('x') or i for i in all[:2]] 
>>> x 
[['x'], ['x']] 

Einige all wird auch eingeführt und u pdated auf eine Liste y:

>>> y = [i.append('y') or i for i in all[1:3]] 

all aktualisiert:

>>> all 
[['x'], ['x', 'y'], ['y'], []] 

Aber x wird ebenfalls aktualisiert:

>>> x 
[['x'], ['x', 'y']] 

Und y wie erwartet generiert:

>>> y 
[['x', 'y'], ['y']] 

Insgesamt, für einfache Aufgaben, würde ich empfehlen, eine for Schleife explizit zu aktualisieren. Dies wird als Python angesehen.

Technisch gesehen, wenn Sie Zugriff auf die Liste Klasse hatte, konnte man dies eine Funktion machen:

def more_functional_append(self, x): 
    self.append(x) 
    return self 
  • functional programming basiert auf jeder Aussage im Wesentlichen eine Sache zu tun, und nicht die Nebenwirkungen (so , nicht mutierend und zurückkehrend). append ist nicht sehr funktional, da es eine Liste mutiert (reine funktionale Programmierung hat nur unveränderliche Objekte) und gibt kein Ergebnis an andere Aktionen (Funktionen) zurück. Mit funktionalen Programmierkonzepten können Sie große große Einzeiler erstellen, die niemand lesen kann, auch bekannt als "Job-Sicherheit" oder "schlechter Code".
+0

Ich habe heute eine andere Sicht auf diese Antwort, also wenn Sie dies lesen, kommentieren Sie bitte, damit ich es aktualisieren kann. Es gibt ein fehlendes Kernmerkmal für die funktionale Programmierung hier, die Unbeweglichkeit ist, und das sollte ich weiter ausführen. –

1

Sie können die Liste zusätzlich innerhalb einer Liste Verständnis verwenden, etwa so:

a = [x + [ 'a'] für x in einem]

Dies ergibt die gewünschte Ergebnis für a. Man könnte es in diesem Fall effizienter machen, indem man [a] einem Variablennamen vor der Schleife zuweist, aber es hängt davon ab, was Sie tun wollen.

0

In der ersten Wertzuweisung Ihres Listenverständnisses ein Attribut Error, "NoneType" -Objekt hat kein Attribut "append", hilft zu erklären, warum Ihre Liste, ein, mit None (s) geladen wird. Um meine Konsole zu veranlassen, den Fehler zu werfen, benutzte ich x als eine Variable für das Listenverständnis und auch als den Iterator.

Traceback (most recent call last): 
x = [x.append('a') for x in a] 
AttributeError: 'NoneType' object has no attribute 'append' 

Dann kehrte ich wieder zu einem for x und es warf den gleichen Fehler.

Traceback (most recent call last): 
a = [x.append('a') for x in a] 
AttributeError: 'NoneType' object has no attribute 'append'