2009-11-26 68 views
5

我有一些變量,我想選擇第一個評估爲True,否則返回一個默認值。Pythonic的方式來選擇第一個變量評估爲True

例如,我有a,bc。我的現有代碼:

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

我正在考慮另一種方法:

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

但他們都覺得凌亂,所以有一個更Python的方式?

+0

我不知道「pythonic」,但我喜歡第一個。尼斯和好聽,易於閱讀:) – mtvee 2009-11-26 12:10:10

+6

你是什麼意思「定義」?例如,如果b未定義,那麼您將得到一個NameError。你的代碼檢查變量是否被定義,但是爲空/零/假。 – 2009-11-26 12:15:18

+3

請注意,在Python中,您不需要定義變量,而是將名稱綁定到對象。 – 2009-11-26 12:20:44

回答

20

您的意思是返回第一個值bool(value)==True?然後,你可以依靠的事實是boolean operators return last evaluated argument

result = a or b or c or default 
+1

NB(對於OP)空字符串('「」')具有false布爾值('bool(「」)== False');請記住,如果你不認爲它在程序中是「假」的話。同樣適用於'()'(空元組),'{}'(空字典),'[]'(空列表)和零(任何數字類型)。 – tzot 2010-02-01 20:05:25

17

如果一個變量沒有被「定義」,則無法訪問它的名字。所以任何對'a'的引用都會引發NameError異常。

在另一方面,如果你有這樣的:

a = None 
b = None 
c = 3 

你可以做

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

asker提供的兩個選項中沒有一個運行到同一個NameErrorException中? – donut 2009-11-26 12:34:37

+1

沒錯。在分配內容之前,您無法讀取變量。 – 2009-11-26 12:44:02

1

不知道,如果這個工程在任何情況下,但是這適用於這種情況。

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

這個怎麼樣?

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

以上打印"default"。如果定義了任何輸入,則val將包含第一個定義的輸入。

5

只要default評估爲真:

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

如果你已經決定使用'next',你可以使用它的'default'參數 – abyx 2009-11-26 12:55:22

2

你可以做這樣的事情(相對於其他答案這是你不定義解決方案的「缺失」值爲是NoneFalse或):

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"]) 

爲了避免NameErrors a,b或c爲沒有定義時:給出的函數字符串的列表,而不是可變的引用(你不能傳遞不存在的引用)。如果您在'globals()'作用域之外使用變量,則可以使用getattr及其默認參數。

-

如果A,B和C的定義,我會去這樣的事情(在考慮到一個空字符串,無或虛假評估爲布爾False):

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

返回後你不需要'bre​​ak':你已經不在循環中。在循環結束時,您也不需要「else:continue」:無論如何,這將會發生。 – 2010-01-31 20:48:00

1

如果defined你的意思是ever assigned any value whatsoever to in any scope accessible from here,然後試圖訪問一個「未定義」變量將引發NameError異常(或某些子類物,但追趕NameError將捕獲子類也是如此)。所以,執行最簡單的方法,從字面上看,絕對怪異的任務,你問一下,就是:

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

任何被指控的解決方案缺乏一個try /除了上述意義下是行不通的「定義」。基於探索特定範圍的方法可能會錯過其他範圍,或者通過嘗試複製eval爲您做的範圍排序邏輯非常複雜。

如果通過「定義」你實際上是指「賦值爲真值(而不是假)」,即所有值實際上是定義爲(但可能碰巧是錯誤的,而你想要第一個真正的價值),那麼已經提出的a or b or c or default成爲最簡單的方法。但是,這是一個完全不同的(甚至更we!)意思是「定義」! - )

相關問題