2015-05-28 18 views
6

Nehmen wir an, ich möchte eine Liste von ints mit Python, die aus den Würfeln der Zahlen 1 bis 10 besteht nur, wenn der Würfel ist gleichmäßig durch vier teilbar.Ist das Listenverständnis pythonisch genug?

Ich schrieb diese Arbeitsleitung:

cube4 = [x ** 3 for x in range(1, 11) if (x ** 3) % 4 == 0] 

Mein Rindfleisch mit dieser Codezeile ist, dass er zweimal den Würfel von X zu berechnen. Gibt es mehr Python Möglichkeit, diese Zeile zu schreiben? Oder ist das so gut, wie es in einem Listenverständnis kommt?


Bearbeiten - Meine Frage soll fokussiert werden, wie Fremd Berechnung zu vermeiden, die Eigenschaften und Nuancen von Python, während immer noch Code übersichtlich und lesbar zu halten. Obwohl diese Lösung wahrscheinlich erreicht worden wäre, andere Fragen zu betrachten, wollte ich sicher sein, dass ich die beste Antwort auf diese Frage wusste, nicht nur eine Lösung, die funktioniert.

+1

Wie es ist, ist es sehr pythonisch und ich würde mir keine Sorgen machen. Sie haben keine Ahnung, was die Laufzeit tut, vielleicht optimiert sie schon den x^3 Begriff. Oder eine zukünftige Version von Python könnte. Oder eine alternative Laufzeit, wie PyPy es könnte. Es ist am besten, den Idiomen der Sprache zu folgen und die Sprachdesigner sich über diese Dinge Gedanken machen zu lassen, es sei denn, Sie haben Ihren Code profiliert und wissen, dass das Listenverständnis Ihr Flaschenhals ist. Wenn Sie zu diesem Punkt kommen, müssen Sie sich darüber Gedanken machen, was Ihre Laufzeit tut. – LiavK

Antwort

16

Sie können einen Generator Ausdruck verwenden:

cubed = (x ** 3 for x in range(1, 11)) 
cube4 = [c for c in cubed if c % 4 == 0] 

Diese noch iteriert über range() nur einmal, aber jetzt ist der x ** 3 Ausdruck wird nur die einmal berechnet als der Generator Ausdruck über iteriert. Sie können es in einer Zeile kombinieren:

cube4 = [c for c in (x ** 3 for x in range(1, 11)) if c % 4 == 0] 

aber den Generator Ausdruck in einer separaten Zeile hält, kann in Verständnis (kein Wortspiel beabsichtigt) unterstützen.

Demo:

>>> [c for c in (x ** 3 for x in range(1, 11)) if c % 4 == 0] 
[8, 64, 216, 512, 1000] 

Natürlich mathematisch gesprochen, für Ihr einfaches Beispiel könnten Sie einfach [x ** 3 for x in range(2, 11, 2)] verwenden, aber ich vermute, das war nicht ganz das Ziel Ihrer Frage. :-)

+0

Ich mag diese Generatorlösung sehr. Dies ist definitiv die Art von Revision, die ich suchte. Ich stimme zu, die Lesbarkeit in zwei Zeilen zu halten, anstatt einen weniger lesbar zu machen. Danke! –

3

Der Würfel einer Zahl ist genau dann durch 4 teilbar, wenn die Zahl gerade ist. Dies ist leicht zu sehen, wenn Sie jede Zahl in ihre Primfaktoren erweitern. Deshalb:

cube4 = [x ** 3 for x in range(1, 11) if x % 2 == 0] 
+1

Sicher, aber das ist nicht der Punkt der Frage, vermute ich. –

1

Ich liebe Einzeiler, aber es ist erwähnenswert, dass es eine andere Art und Weise Pythonic die gewünschte list zu erzeugen.

cube4 = [] 
for x in range(1, 11): 
    y = x ** 3 
    if not y%4: 
     cube4.append(y)