2012-04-15 2 views
0

ich mit einer Python-Version zu tragen habe < 2.5 (es ist 2.4.3 für Einzelheiten)Der beste Weg, ternäre conditionals in Python zu tun <2,5

Es scheint, dass ternäre Operatoren waren einleiten in Python 2.5 starten. Für diejenigen, die in Python> = 2.5 aussehen wie diese nicht vertraut, ternäre Operatoren sind:

def do_ternary(flag): 
    return "foo" if flag else "bar" 

würde Ich mag einige Lösungen wissen, dass dies in den frühen Versionen von Python zu emulieren. Ich kann sicher tun, wenn ... sonst, aber ich bin auf der Suche nach etwas mehr Python, dass ich nicht schämen würde, einige Produktions-Code zu setzen :)

Vielen Dank für die Hilfe!

+0

ist Ihr Einwand gegen wenn Flag: zurück "foo" sonst: zurück "bar", dass es nicht stilvoll genug ist? oder gibt es einen konkreten Grund? – mfrankli

+0

gut die Logik ist in Ordnung, aber es ist kein ternärer Operator. Es ist nicht wirklich eine Frage von "stilvoll" oder nicht, es geht eher um Code-Faktorisierung und das Schreiben von sauberem Code. Ich mag nicht wirklich ganze Bäume, wenn ... andere Aussagen in meinem Code. –

+2

Wenn Sie etwas tun wollen, wenn ein Test wahr ist, und etwas anderes, dann erscheint '' if ...: ... else: ... '' ziemlich vernünftig. Verwechsle nicht _terse_ und _readable_. Lesbar sollte immer gewinnen, wenn Sie beides nicht können. –

Antwort

4

Eigentlich im Web Ich war auf der Suche und finde, was wie eine wirklich elegante pythonic Lösung scheint:

def _if(test): 
    return lambda alternative: \ 
       lambda result: \ 
        [delay(result), delay(alternative)][not not test]() 

def delay(f): 
    if callable(f): return f 
    else: return lambda: f 

>>> fact = lambda n: _if (n <= 1) (1) (lambda: n * fact(n-1)) 
>>> fact(100) 
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000L 

Was denken Sie über dieses? Es sieht meiner Meinung nach ziemlich sauber und leicht lesbar aus.

+0

Ich denke, es ist verdammt cool :) Ich muss aber sagen, soweit es die Lesbarkeit betrifft, wenn ... dann sind Aussagen ziemlich lesbar. –

+1

Ja, ich stimme zu, wenn ... sonst sind die lesbarsten, aber ich versuche nur, kreativ zu sein und einen One-Liner zu haben, um den Trick zu machen :) Bisher glaube ich, dass diese und @ TokenMacGuy's diejenigen sind, die ich ' Ich betrachte die meisten. –

+0

Ich denke, dies ist möglicherweise der am wenigsten lesbare Code, den ich gesehen habe, um dies zu tun. Während es ein cooles Stück Code ist, habe ich wirklich nicht das Gefühl, dass es tatsächlich einen Vorteil für den Leser oder Schreiber bietet. –

1

Der klassische 'Trick' verwendet, dies zu tun ist:

test and true_value or false_value 

Dies funktioniert wie and und or Arbeit wie so in Python:

x or y -> if x is false, then y, else x 
x and y -> if x is false, then x, else y 

Source

Das bedeutet, dass wir bekomme das ungefähr gleiche Ergebnis - solange true_value zu True auswertet - also zum Beispiel fol Muhen würde nicht Arbeit:

flag and [] or "bar" 

Als [] ausgewertet False.

Ich würde immer noch argumentieren, dass dies weniger lesbar ist als einfach mit einem if/else-Block, denn es sei denn, Sie sind damit vertraut, es ist unklar.

Also würde ich raten, mit:

if test: 
    return true_value 
else: 
    return false_value 

(Ersatz Rückkehr mit Zuordnung oder was auch immer, wo erforderlich).

+5

Beachten Sie, dass dies nicht wie erwartet funktioniert, wenn 'true_value' etwas ist, das zu' False' ausgewertet wird, z. in 'flag und [] oder" bar "'. – Dougal

+0

@Dougal +1. Ich füge diese Notiz hinzu - ich habe das selbst nie gemocht und habe es nie benutzt, habe dieses Problem vergessen. –

4

Ein gemeinsamer Trick ist list-Indizierung zu verwenden, da False/True wiederum in 0/1, wenn eine ganzen Zahl erforderlich ist. Im Fall kann der Test eher falsch-y oder Wahrheit-y als ein boolean, seine gute Praxis, zunächst den Test sicherzustellen, ist ein boolean:

["bar", "foo"][bool(flag)] 

wird die gleiche Leistung wie die ternären in Ihrer Frage produzieren.

Edit: Dougal weist darauf hin, dass dies etwas anders als das ternäre verhalten kann, weil sowohl die wahren und falschen Werte ausgewertet werden, die Nebenwirkungen haben können.

+0

das ist eine gute Alternative, aber ich fühle es ist ein bisschen in Bezug auf die Lesbarkeit fehlt. Einer der Vorteile von ternären Operationen ist, dass es einfach zu lesen ist, und obwohl das gut funktioniert, ist es auch komplex, um den Code zu komplexieren. –

+0

Dies schließt auch die Auswertung nicht kurz. – Dougal

+0

@Dougal Das ist ein guter Punkt. –

7

die richtige Weise, dass all die Dinge tut, dass if/else tut, ist:

(condition and (yes_value,) or (no_value,))[0] 

das tut sowohl den Kurzschluss und löst das Problem, wann yes_value selbst Falsey.Offensichtlich, wenn Sie Grund haben, diesen Cludge zu vermeiden, tun Sie das einfach; in Ihrem Beispiel sind beide Bedingungen konstante Ausdrücke, so können Sie dies tun:

{True: yes_value, False: no_value}[bool(condition)] 

oder mehr kurz und bündig:

(no_value, yes_value)[condition] 

wenn Sie brauchen die kurze circut zu tun, aber Sie sind sicher, dass die yes_value ist nie Falsey, können Sie die Tupel trimmen:

condition and yes_value or no_value 

aber das ist wahrscheinlich nur dann gültig, wenn die yes_value tatsächlich eine konstante ist. Wenn keiner von ihnen nach Ihrem Geschmack oder Bedürfnissen anzupassen, verwenden Sie nur eine plain-ol if: Aussage, mit einer Zwischengröße

if condition: 
    result = yes_value 
else: 
    result = no_value 
Verwandte Themen