2009-11-26 10 views
5

Ich habe einige Variablen und möchte die erste Variable auswählen, die True ergibt oder einen Standardwert zurückgibt.Pythonische Methode zur Auswahl der ersten Variablen, die zu True ausgewertet wird

Zum Beispiel habe ich a, b und c. Mein vorhandener Code:

result = a if a else (b if b else (c if c else default)) 

Ein weiterer Ansatz, den ich erwäge:

result = ([v for v in (a, b, c) if v] + [default])[0] 

Aber sie beide das Gefühl, chaotisch, so ist es eine Pythonic Art und Weise?

+0

ich weiß nicht über "Pythonic", aber ich mag die erste. schön und lispy und einfach zu lesen :) – mtvee

+6

Wie meinst du "definiert"? Wenn b zum Beispiel nicht definiert ist, erhalten Sie einen NameError. Ihr Code prüft, ob die Variablen definiert sind, aber leer/Null/Falsch. –

+3

Beachten Sie, dass Sie in Python keine Variablen definieren, sondern Namen an Objekte binden. –

Antwort

20

Meinen Sie den ersten Wert für was bool(value)==True? Dann können Sie einfach verlassen sich auf die Tatsache, dass boolean operators return last evaluated argument:

result = a or b or c or default 
+1

NB (zum OP) die leere Zeichenkette (' "" ') hat eine falsche boolescher Wert ('bool (" ") == False'); Denken Sie daran, wenn Sie es in Ihrem Programm nicht als "falsch" betrachten. Gleiches gilt für '()' (leeres Tupel), '{}' (leeres Diktat), '[]' (leere Liste) und Null (in einem beliebigen numerischen Typ). – tzot

17

Wenn eine Variable nicht „definiert“, Sie seinen Namen nicht zugreifen können. Jeder Verweis auf 'a' löst eine NameError-Ausnahme aus.

In der anderen Seite, wenn Sie etwas haben, wie:

a = None 
b = None 
c = 3 

Sie tun können,

default = 1 
r = a or b or c or default 
# r value is 3 
+0

Würde keine der beiden Optionen, die der Asker präsentierte, in dieselbe NameErrorException laufen? – donut

+1

Das stimmt. Sie können eine Variable nicht lesen, bevor Sie ihr etwas zuweisen. –

1

Sie wissen nicht, ob dies in jedem Fall funktioniert, aber das funktioniert für diesen Fall.

a = False 
b = "b" 
c = False 
default = "default" 
print a or b or c or default # b 
1

Wie wäre es damit?

a=None 
b=None 
c=None 
val= reduce(lambda x,y:x or y,(a,b,c,"default")) 
print val 

Die obigen Drucke "default". Wenn einer der Eingänge definiert ist, enthält val den ersten definierten Eingang.

5

Solange default ausgewertet True:

result = next((x for x in (a, b, c, d , e, default) if x)) 
+4

Wenn Sie sich für 'next' entschieden haben, können Sie auch das' default' Argument – abyx

2

Sie so etwas tun könnte (im Gegensatz zu den anderen Antworten ist dies eine Lösung, bei der Sie nicht müssen definieren die ‚fehlenden‘ Werte als entweder None oder False) ist:

b = 6 
c = 8 

def first_defined(items): 
    for x in items: 
     try: 
      return globals()[x] 
      break 
     except KeyError: 
      continue 

print first_defined(["a", "b", "c"]) 

um NameErrors zu vermeiden, wenn a, b oder c nicht definiert ist: die Funktion, eine Liste von Zeichenfolgen geben, anstatt variable Referenzen (Sie können nicht vorhandene Referenzen nicht übergeben). Wenn Sie Variablen außerhalb des Bereichs 'globals()' verwenden, können Sie getattr mit seinem Standardargument verwenden.

-

Wenn a, b und c definiert sind, für so etwas gehen würde (unter Berücksichtigung der Tatsache, dass ein leerer String, keine oder falsch in einen Booleschen False bewerten):

a = None 
b = 6 
c = 8 

def firstitem(items): 
    for x in items: 
     if x: 
      return x 
      break 
     else: 
      continue 

print firstitem([a, b, c]) 
+1

verwenden. Sie müssen nach einer Rückgabe nicht 'brechen': Sie sind bereits außerhalb der Schleife. Am Ende einer Schleife müssen Sie auch nicht 'sonst: weiter' machen: das würde sowieso passieren. –

1

Wenn durch defined Sie meinen, ever assigned any value whatsoever to in any scope accessible from here, dann wird der Versuch, auf eine "undefined" Variable zuzugreifen, eine NameError Ausnahme auslösen (oder eine Unterklasse davon, aber fangen NameError wird auch die Unterklasse fangen).So ist die einfachste Art und Weise durchzuführen, buchstäblich, die absolut seltsame Aufgabe, die Sie fragen, ist:

for varname in ('a', 'b', 'c'): 
    try: return eval(varname) 
    except NameError: pass 
return default 

Jede fehlt angebliche Lösung eine try/except nicht für „definiert“ unter der obigen Bedeutung arbeiten. Ansätze, die auf der Erkundung bestimmter Bereiche basieren, werden entweder andere Bereiche vermissen oder ziemlich komplex sein, wenn Sie versuchen, die für Sie so einfache Bereichsanordnungslogik zu replizieren, die eval für Sie ist.

Mit "definiert" meinen Sie eigentlich "zugewiesen einen Wert, der wahr (im Gegensatz zu false) auswertet", dh alle Werte sind tatsächlich definiert (aber möglicherweise falsch sein, und Sie wollen die erste true value), dann wird der bereits vorgeschlagene a or b or c or default zum einfachsten Ansatz. Aber das ist eine völlig andere (und noch seltsamer!) Bedeutung für das Wort "definiert"! -)

Verwandte Themen