2015-06-22 17 views
8

Wie haben Sie eine mehrzeilige Aussage in einem Listenverständnis oder Eval?Python 2 Liste Verständnis und eval

Ich habe versucht, diesen Code zu aktivieren:

def f(x, y, b=''): 
    for i in x: 
     if i in y: 
      y.remove(i) 
      i *= 2 
     b += i 
    return b 

in einer Lambda-Funktion wie folgt:

j=lambda x,y:''.join(eval('y.remove(i);i*2')if i in y else i for i in x) 

In beide x ist eine Zeichenkette wie 'onomatopoeia' und y ist eine Liste wie ['o','a','o'] .

Aber aus irgendeinem Grund gibt es einen Syntaxfehler zurück. Kann das jemand erklären?

+0

Was sind Werte von 'x' und' y'? –

+0

Ich glaube, Lambdas sind absichtlich auf eine Zeile beschränkt, um die Lesbarkeit und Klarheit zu verbessern. Sie könnten versuchen, diese Funktion in Lambda umzuwandeln, aber es ist ein bisschen kontrapythonisch. – J0HN

+0

'eval' benötigt einen Ausdruck, während' y.remove (i); i * 2' eine Anweisung ist. 'eval ('1; 1')' erzeugt auch einen 'SyntaxError'. – nymk

Antwort

3

Zuerst sollten Sie dies wahrscheinlich nicht mit einem Lambda wegen der Nebenwirkungen in der Schleife umschreiben. Wenn du trotzdem willst, benutze kein eval.

würde ich vorschlagen:

j = lambda x, y: ''.join((y.remove(i) or 2 * i) if i in y else i for i in x) 

Da das Ergebnis von Entfernen None-or das zweite Argument wird das Ergebnis sein. Dies vermeidet die Bewertung. Aber es ist immer noch schlimmer als eine For-Schleife.


Wie auf die ursprüngliche Frage in den Kommentaren erwähnt, ist 2 * y.pop(y.index(i)) besser lesbar als die or Konstrukt. Sie werden zweimal über y laufen, aber die Leistung scheint nicht das Problem zu sein.

2

Ich würde Ihre Funktion sehr bevorzugen, aber das wird tun, was Sie wollen.

from itertools import chain 
j = lambda x, y: ''.join(filter(None,chain.from_iterable((i * 2,y.remove(i)) if i in y else i for i in x))) 

print(j("'onomatopoeia'",['o','a','o'])) 
'oonoomaatopoeia' 
+1

Warum nicht einfach' '' .join (2 * y.pop (y.index (i)) wenn ich in y sonst ich für i in x) '? – l4mpi

+0

@ l4mpi, weil ich den OP-eigenen Code verwende, hat die Indexierung auch einen Preis, also nicht wirklich besser als nur das Filtern. Ich würde keinen der beiden Ansätze verwenden, wenn es nach mir ginge. –

+0

Ich stimme zu, dass keiner wirklich der richtige Weg ist, aber die "Pop" -Variante ist viel besser lesbar. Ich bezweifle, dass Geschwindigkeit ein Problem ist, und wenn es dann wäre, den Aufruf "Entfernen" vollständig zu eliminieren, wäre wahrscheinlich die beste Vorgehensweise (z. B. mit einem "Zähler" und abnehmenden Buchstabenzählungen). – l4mpi

0

Wenn Sie gute funktionelle Ausdrücke schreiben wollen (lambda s verwenden, map, reduce, filter und so weiter), sollten Sie Nebenwirkungen vermeiden.

Ich würde stark Ihren Code als Funktion lieber als ein Lambda mit Nebenwirkungen bevorzugen.

Dies ist ein Nebeneffekt freie Umsetzung in einem Lambda-Ausdruck:

>>> from functools import reduce 
>>> (lambda x, y: reduce(lambda a, b: \ 
...  (a[0]+2*b, a[1][:a[1].index(b)]+a[1][a[1].index(b)+1:]) if b in a[1] \ 
...  else (a[0]+b, a[1]), x, ('',y))[0])('onomatopoeia', ['o','a','o']) 
'oonoomaatopoeia' 

Ich fürchte, es nicht kurz noch schöne noch einfach ist zu verstehen * wie man es haben wollen würde für ein Lambda. :/ (hoffentlich kann jemand eine Verbesserung vorschlagen)

Nur ein Gegenbeispiel, um die Verwendung eines Lambda in diesem Zusammenhang zu verhindern.

IMHO das größte Problem mit Lambdas in Python ist, dass es keine where Syntax wie in Standard-ML gibt, um variable Aliase im selben Ausdruck zu definieren. Also, die Dinge werden ziemlich schnell hässlich für alles, was nicht trivial ist.


Wenn Sie daran interessiert sind, zu verstehen, was es tut, ist die Idee zu verwenden, zu verringern, eine Automat zu laufen, wo das Ergebnis (bei jedem Schritt) der „Zustand“ der Berechnung ist.

Der anfängliche "Zustand" ist ('', ['o','a','o']), und die Reduce-Funktion führt den Austausch nach Bedarf durch, beginnend mit 'onomatopoeia'.

Dies ist die Entwicklung der „Staat“:

('',  ['o','a','o']) 'o' 
('oo',  ['a','o']) 'n' 
('oon',  ['a','o']) 'o' 
('oonoo',  ['a']) 'm' 
('oonoom',  ['a']) 'a' 
('oonoomaa',  []) 't' 
('oonoomaat',  []) 'o' 
('oonoomaato',  []) 'p' 
('oonoomaatop',  []) 'o' 
('oonoomaatopo', []) 'e' 
('oonoomaatopoe', []) 'i' 
('oonoomaatopoei', []) 'a' 
('oonoomaatopoeia', []) 

und wir nehmen nur das erste Element des letzten Zustand.