Frage Wenn oder elif entweder wahr dann tu etwas


Dies ist nur für akademisches Interesse. Ich stoße sehr oft auf die folgende Situation.

either_true = False
if x:
  ...do something1
  either_true = True
elif y:
  ...do something2
  either_true = True
if either_true:
  ..do something3

Gibt es irgendeine pythonische Art, dies zu tun, oder im allgemeinen eine bessere Programmierung? Grundsätzlich wird something3 nur ausgeführt, wenn oder elif wahr ist.


44
2018-02-13 14:04


Ursprung


Antworten:


Dein Code ist fast optimal, soweit es sich um Codewiederholung und -auswertung handelt. Das einzige, was ich mir vorstellen kann, um Wiederholungen zu vermeiden, wäre:

# be optimistic!
either_true = True
if x:
    do_something1
elif y:
    do_something2
else:
    either_true = False

if either_true:
    do_something3

Dadurch wird eine Zuweisung entfernt, obwohl sich die Gesamtanzahl der Zeilen nicht ändert.

Der Vorteil ist, dass dies funktioniert n Bedingungen, ohne eine andere Zuweisung hinzufügen, während Ihre aktuelle Lösung ein erfordert either_true = True für jeden Zustand.

Meiner Meinung nach haben sie ungefähr den gleichen Grad an Lesbarkeit, aber der obige Code wird mit mehr Bedingungen besser sein.

Außerdem gibt es keinen "pythonischen" Weg, außer einer lesbaren Lösung, die Code-Wiederholungen vermeidet und hinsichtlich der Effizienz optimal ist, und ich kenne keine "bessere Programmierung", um dasselbe Ergebnis zu erzielen.


31
2018-02-13 20:14



Sie könnten auch das weglassen either_true vollständig kennzeichnen wenn doSomething3 ist eine einzelne Codezeile (z. B. ein Funktionsaufruf):

if x:
  ..do something 1
  ..do something 3
elif y:
  ..do something 2
  ..do something 3

Es behält die nette Eigenschaft der Bewertung bei x und y höchstens einmal (und y wird nicht ausgewertet, wenn x ist wahr).


35
2018-02-13 14:12



Ich würde damit umgehen, indem ich geschachtelte if-Anweisungen verwende, d.h.

if x or y:
    if x:
        ...do something1
    elif y:
        ...do something2
    ...do something3

Wie einige Kommentare gezeigt haben, hängt die beste Lösung davon ab, was x & y sind. Wenn leichte Lesbarkeit / prägnanter Code Ihr Ziel ist, sollten diese oder andere Antworten in Ordnung sein. Wenn jedoch x & y teure Funktionsaufrufe wären, wäre es besser, etwas mehr zu tun, als das, was Sie getan haben, um zu vermeiden, die Funktion zweimal aufzurufen.


19
2018-02-13 14:07



Sie könnten etwas davon in eine Funktion einfügen:

def do_stuff():
    if x:
        ...do something1
        return True
    elif y:
        ...do something2
        return True
    else:
        return False

if do_stuff():
    ..do something3

Oder alles in einer Funktion:

def do_stuff()
    if x:
        ...do something1
    elif y:
        ...do something2
    else:
        return

    ..do something3

7
2018-02-13 14:11



Im Sinne einer völlig anderen Lösung als die bereits vorgeschlagenen, könnten Sie eine Liste strukturierter Wörterbücher einrichten, mit der Sie mehrere Fälle einrichten können, die an Ihre vordefinierten "Somethings" gebunden sind.

cases = [
    {'condition' : x, 'action' : something1},
    {'condition' : not x and y, 'action' : something2},
    {'condition' : x or y, 'action' : something3},
]

for c in cases:
    if c['condition']: c['action']

Ich mag diese Methode wirklich (und ich habe sie gerade erst entdeckt, als ich versuchte, eine einzigartige Antwort auf diese Frage zu finden, danke!) - es ist wirklich offensichtlich, welcher Fall an welche Aktion gebunden ist, und es ist einfach, mehrere hinzuzufügen Fälle, ohne weitere if / else-Anweisungen hinzuzufügen.


6
2018-02-13 17:45



if x or y:
    dosomethig1() if x else dosomething2()
    dosomething3()

Natürlich wird dies ausgewertet x.__nonzero__ zweimal. Normalerweise ist das keine große Sache, aber wenn es teuer ist, können Sie das immer im Voraus auswerten und es in eine temporäre Variable speichern.


5
2018-02-13 14:08



Für alle diese Vorschläge und andere, die Sie sich vorstellen, beachten Sie, dass wenn x und y sind teure Ausdrücke:

if askTheServer() or readTheOneGigabyteConfigFile():
   ...

Sie können die Werte, die diese Ausdrücke zurückgeben, zuerst den schnell auswertbaren Variablen zuweisen:

x = askTheServer()
y = readTheOneGigabyteConfigFile()
if x or y :
   ...

4
2018-02-14 00:37



either_true = x or y
if x:
  ...do something1
elif y:
  ...do something2
if either_true:
  ..do something3

2
2018-02-13 14:14