2009-04-21 9 views
8

Ist es möglich, so etwas zu haben:Mehrere Anweisungen in Listenbeziehungen in Python?

list1 = ... 

currentValue = 0 
list2 = [currentValue += i, i for i in list1] 

ich versucht, aber hat nicht funktioniert? Was ist die richtige Syntax, um diese zu schreiben?

EDIT: Die Druckanweisung war ein Beispiel. Tatsächlich inkrementiere ich einen Wert außerhalb der Schleife.

+0

Was ist los mit der gewöhnlichen for-Anweisung? Warum sollten Sie sich damit beschäftigen, wenn Sie eine vollkommen gute Aussage haben? Was versuchst du zu erreichen? –

+1

Nichts, ich möchte nur sehen, ob es möglich ist, Listen mit Python-Listen zu erstellen. –

Antwort

23

Anweisungen kann nicht innerhalb von Ausdrücken in Python gehen; Es war eine Komplikation, die bewusst aus der Sprache heraus entwickelt wurde. Versuchen Sie für dieses Problem, eine Komplikation zu verwenden, die tat es in die Sprache machen: Generatoren.Sehen Sie:

def total_and_item(sequence): 
    total = 0 
    for i in sequence: 
     total += i 
     yield (total, i) 

list2 = list(total_and_item(list1)) 

Der Generator hält eine laufende Zählung der bisher gesehen Artikel, und Präfixe es zu jedem Element, so wie es aussieht wie Sie Beispiel zu tun versucht. Natürlich ist eine einfache Schleife noch einfacher, die oben eine leere Liste erstellt und nur append() aufruft! :-)

+0

+1 für die Erwähnung, dass Aussagen von Ausdrücken ausgeschlossen sind (geschweige denn _multiple_ Anweisungen :-), plus die Empfehlung von expliziteren Ansätzen. –

0

Zunächst möchten Sie wahrscheinlich nicht print verwenden. Es gibt nichts zurück, also verwenden Sie eine herkömmliche for-Schleife, wenn Sie nur Dinge ausdrucken möchten. Was Sie suchen ist:

>>> list1 = (1,2,3,4) 
>>> list2 = [(i, i*2) for i in list1] # Notice the braces around both items 
>>> print(list2) 
[(1, 2), (2, 4), (3, 6), (4, 8)] 
2

Ich bin nicht ganz sicher, was Sie versuchen zu tun, aber es ist wahrscheinlich so etwas wie

list2 = [(i, i*2, i) for i in list1] 
print list2 

Die Aussage in der Liste Verständnis eine einzige zu sein hat Aussage, aber man konnte es immer einen Funktionsaufruf:

def foo(i): 
    print i 
    print i * 2 
    return i 
list2 = [foo(i) for i in list1] 
2

Hier ist ein Beispiel von another question:

[i for i,x in enumerate(testlist) if x == 1] 

Der Enumerate-Generator gibt ein 2-Tupel zurück, das in i, x geht.

1

Drucken ist eine seltsame Sache, um ein Listenverständnis aufzurufen. Es würde helfen, wenn Sie uns zeigen, welche Ausgabe Sie wollen, nicht nur der Code, der nicht funktioniert.

Hier sind zwei Vermutungen für Sie. In jedem Fall ist der wichtige Punkt, dass die Wertangabe in einem Listenverständnis ein einzelner Wert sein muss. Sie können nicht mehrere Objekte gleichzeitig einfügen. (Wenn das, was Sie versuchen, mit dem zweiten Beispiel zu tun, überspringen.)

list1 = [1, 2, 3] 
list2 = [(i, i*2, i) for i in list1] 
# list2 = [(1, 2, 1), (2, 4, 2), (3, 6, 3)] 

Um eine flache Liste zu erhalten:

list1 = [1, 2, 3] 
tmp = [(i, i*2) for i in list1] 
list2 = [] 
map(list2.extend, tmp) 
# list2 = [1, 2, 1, 2, 4, 2, 3, 6, 3] 

Edit: Inkrementieren einen Wert in der Mitte der Liste Verständnis ist immer noch seltsam. Wenn Sie es wirklich tun müssen, ist es besser, wenn Sie nur eine reguläre for-Schleife schreiben und Werte hinzufügen, während Sie fortfahren. In Python wird eine solche Schlauheit fast immer als "unpythonisch" gebrandmarkt. Tun Sie es, wenn Sie müssen, aber Sie werden kein Ende der Flak in Foren wie diesem bekommen. ;)

+0

Danke im Grunde muss ich einen Wert außerhalb des Listenverständnisses erhöhen. –

+0

Können Sie schreiben, was Sie tun, als eine "für Artikel in list1" Schleife? Es wird einfacher sein, herauszufinden, ob es für ein Listenverständnis so geeignet ist. – ojrac

0

Sie können nicht mehrere Anweisungen ausführen, aber Sie können einen Funktionsaufruf ausführen. Zu tun, was Sie scheinen oben zu wollen, könnten Sie tun:

list1 = ... 
list2 = [ (sum(list1[:i], i) for i in list1 ] 

im Allgemeinen, da Listenkomprehensionen Teil der ‚funktionellen‘ Teil von Python sind, sind Sie zu ... Funktionen beschränkt. Andere Leute haben vorgeschlagen, dass Sie Ihre eigenen Funktionen schreiben können, wenn nötig, und das ist auch ein gültiger Vorschlag.

+0

Generiert dies nicht n Listen, wobei n die Länge der ersten Liste ist? Das Ergebnis, wenn die Liste aus Tausenden von Elementen bestand, konnte viel zu lange dauern. –

+0

Sicher, aber Effizienz war nicht das Ziel - ein Listenverständnis zu verwenden war. Ihre Generatorlösung ist offensichtlich viel effizienter. – pjz

1

Für Ihre editierten Beispiel:

currentValue += sum(list1) 

oder:

for x in list1: 
    currentValue += x 

Listenkomprehensionen groß sind, ich liebe sie, aber es ist nichts falsch mit dem bescheidenen for Schleife und Sie shouldn‘ Ich habe Angst, es zu benutzen :-)

EDIT: "Aber was ist, wenn ich anders als die gesammelten Werte erhöhen?"

Nun, was willst du erhöhen? Sie haben die gesamte Macht von Python auf Ihrem Befehl!

Inkrement von x-squared?

for x in list1: 
    currentValue += x**2 

Inkrement um eine Funktion von x und seine Position in der Liste?

for i, x in enumerate(list1): 
    currentValue += i*x 
+0

Aber was ist, wenn ich anders als die gesammelten Werte erhöhen möchte? –

1

Warum würden Sie eine doppelte Liste erstellen. Es scheint, als würde das ganze Listenverständnis nur den Inhalt summieren.

Warum nicht einfach.

list2 = list(list1) #this makes a copy 
currentValue = sum(list2) 
2

Wie PJZ gesagt, Sie Funktionen nutzen zu können, so dass hier können Sie einen Verschluss verwenden Spur des Zählerwert zu halten:

# defines a closure to enclose the sum variable 
def make_counter(init_value=0): 
    sum = [init_value] 
    def inc(x=0): 
     sum[0] += x 
     return sum[0] 
    return inc 

Dann tun Sie, was Sie mit list1 wollen:

list1 = range(5) # list1 = [0, 1, 2, 3, 4] 

Und jetzt mit nur zwei Linien, erhalten wir list2:

counter = make_counter(10) # counter with initial value of 10 
list2 = reduce(operator.add, ([counter(x), x] for x in list1)) 

Am Ende list2 enthält:

[10, 0, 11, 1, 13, 2, 16, 3, 20, 4] 

das ist, was Sie wollen, und Sie können den Wert des Zählers nach der Schleife mit einem Anruf erhalten:

counter() # value is 20 

Schließlich können Sie ersetzen das Schließkram bei jeder Art von Operation, die du willst, hier haben wir ein Inkrement, aber es liegt wirklich an dir. Beachten Sie auch, dass wir eine list2 abzuflachen verwenden zu verringern, und dieser kleine Trick erfordert, dass Sie Operator vor dem Aufruf die Linie mit der Verringerung importieren:

import operator