2010-12-13 4 views
3

Wie der Titel sagt, gibt es eine Möglichkeit, Variablen (d. H. Listen) zu benennen, die innerhalb eines geschachtelten Listenverständnisses in Python verwendet werden?Benennen von Variablen innerhalb von verschachtelten Listen in Python?

Ich könnte ein passendes Beispiel finden, aber ich denke, die Frage ist klar genug. Hier

ist ein Beispiel für Pseudocode:

[... [r for r in some_list if r.some_attribute == something_from_within_this_list comprehension] ... [r for r in some_list if r.some_attribute == something_from_within_this_list comprehension] ...]

Gibt es eine Möglichkeit, die Wiederholung hier zu vermeiden und einfach eine Variable für diese temporäre Liste hinzufügen nur für die Verwendung in der Liste Verständnis?

Erläuterung: Das Listenverständnis funktioniert bereits gut, es ist also keine Frage von "kann es mit einem Listenverständnis getan werden". Und es ist auch schneller als es die ursprüngliche Form einer for-Anweisung ist, also ist es auch nicht eine dieser "for statements vs liste comprehensions" -Fragen. Es geht einfach darum, das Listenverständnis lesbarer zu machen, indem man Variablennamen für Variablen innerhalb des Listenverständnisses alleine erstellt. Ich habe nur wirklich gegoogelt und keine Antwort gefunden. Ich fand this und this, aber das ist nicht wirklich, was ich danach bin.

+0

Unklar. Meinst du "wie soll ich meine Variablen nennen?" oder meinst du "wie kann ich Variablen innerhalb eines Listenverständnisses zuordnen?" oder meinst du "wie niste ich List Comprehensions?" oder etwas ganz anderes? –

+5

'aber ich denke, die Frage ist klar genug. 'Ernsthaft? -1 – Falmarri

+0

Uh ja, ein Beispiel wäre gut. –

Antwort

3

Basierend auf meinem Verständnis von dem, was Sie tun wollen, Nein, Sie kann es nicht tun.

Sie können Zuordnungen in Listenkomprehensionen nicht durchführen, da eine Liste Verständnis im Wesentlichen von der Form

[expression(x, y) for x in expression_that_creates_a_container 
        for y in some_other_expression_that_creates_a_container(x) 
        if predicate(y, x)] 

Zugegeben, es ein paar andere Fälle sind, aber sie sind alle über so. Beachten Sie, dass nirgendwo Platz für eine Aussage ist, was eine Namenszuweisung ist. Sie können also keinen Namen im Kontext eines Listenverständnisses zuweisen, außer indem Sie die for my_variable in Syntax verwenden.

Wenn das Listenverständnis funktioniert, können Sie es veröffentlichen und sehen, ob es vereinfacht werden kann. Lösungen auf Basis von itertools sind oft eine gute Alternative zu umfangreichen Listen.

+0

Am Ende des Tages ist es eher eine visuelle Verbesserung als eine technische. Ich bin schon ziemlich glücklich mit dem Listenverständnis wie es ist. Danke für die 'itertools' Tipps, aber ich habe dieses sehr praktische Modul übersehen. – c00kiemonster

0

Ich werde hier nur ein wenig aussteigen, weil ich keine Ahnung habe, was du wirklich versuchst zu tun. Ich werde nur vermuten, dass Sie versuchen, mehr zu schüren, als Sie in einem einzigen Ausdruck sein sollten. Tu das nicht, nur Teilausdrücke zu Variablen zuweisen:

sublist = [r for r in some_list if r.some_attribute == something_from_within_this_list comprehension] 
composedlist = [... sublist ... sublist ...] 
+0

Ich könnte das tun, aber ich die Unterliste sind durch Bedingungen aus dem Listenverständnis selbst gemacht. Macht es unmöglich, außerhalb des Listenverständnisses zu kommen. – c00kiemonster

+0

@ c00kiemonster in diesem Fall, bezweifle ich, was Sie tun möchten, kann mit List Comprehensions getan werden. Verwenden Sie für Schleifen. –

+0

@ c00kiemonster - es klingt, als würden Sie davon profitieren, [Generatoren] (http://wiki.python.org/moin/Generators) mit ein wenig Filterung anstelle von Listenergänzungen zu verwenden. – detly

2

Ich denke, ich verstehe genau, was Sie meinten, und ich kam zu einer "Teillösung" für dieses Problem. Die Lösung funktioniert gut, ist aber nicht effizient.

Lassen Sie mich mit einem Beispiel erklären:

Ich war nur ein Pythagoreische Triplett zu lösen versuchen, die Summe 1000. Der Python-Code war es zu lösen ist einfach:

def pythagoreanTriplet(sum): 
    for a in xrange(1, sum/2): 
     for b in xrange(1, sum/3): 
      c = sum - a - b 
      if c > 0 and c**2 == a**2 + b**2: 
       return a, b, c 

Aber ich wollte Code es in einem funktionalen Programmierung-Stil:

def pythagoreanTriplet2(sum): 
    return next((a, b, sum-a-b) for a in xrange(1, sum/2) for b in xrange(1, sum/3) if (sum-a-b) > 0 and (sum-a-b)**2 == a**2 + b**2) 

wie im Code zu sehen, ich calc 3-mal (sum-ab), und ich wollte das Ergebnis in einem internen varible speichern zu vermeiden redundante Berechnung.Der einzige Weg, ich fand, dass zu tun, war durch eine weitere Schleife mit einem einzigen Wert das Hinzufügen einer internen Variablen zu deklarieren:

def pythagoreanTriplet3(sum): 
    return next((a, b, c) for a in xrange(1, sum/2) for b in xrange(1, sum/3) for c in [sum-a-b] if c > 0 and c**2 == a**2 + b**2) 

Es funktioniert gut ... aber wie ich an der von der Post beginnen, sagte, ist kein effiziente Methode. Vergleicht man die 3-Methoden mit cProfile, die Zeit für jedes Verfahren erforderlich ist, ist der nächste:

  • Erste Methode: 0,077 Sekunden
  • Secnd Methode: 0,087 Sekunden
  • Dritte Methode: 0,109 Sekunden
1

Einige Leute könnten das Folgende als "Hack" einstufen, aber es ist in einigen Fällen definitiv nützlich.

f = lambda i,j: int(i==j) #A dummy function (here Kronecker's delta)  
a = tuple(tuple(i + (2+f_ij)*j + (i + (1+f_ij)*j)**2 
       for j in range(4) 
       for f_ij in (f(i,j),)) #"Assign" value f(i,j) to f_ij. 
      for i in range(4)) 
print(a) 
#Output: ((0, 3, 8, 15), (2, 13, 14, 23), (6, 13, 44, 33), (12, 21, 32, 93)) 

Dieser Ansatz ist besonders praktisch, wenn die Funktion f teuer ist zu bewerten. Weil es etwas ungewöhnlich ist, kann es eine gute Idee sein, die "Zuweisungs" -Zeile zu dokumentieren, wie ich oben getan habe.