2011-10-14 55 views
15

說我有一本字典,並且我想檢查一個密鑰是否映射到非空值。這樣做的一個方法是Len函數:檢查字典中的值是否定義/長度爲零的最Pythonic方法

mydict = {"key" : "value", "emptykey" : ""} 
print "True" if len(mydict["key"]) > 0 else "False" # prints true 
print "True" if len(mydict["emptykey"]) > 0 else "False" # prints false 

然而,一個可以依靠的Python的語義,以及如何當一個對象被定義它的計算結果爲真,離開了LEN電話:

mydict = {"key" : "value", "emptykey" : ""} 
print "True" if mydict["key"] else "False" # prints true 
print "True" if mydict["emptykey"] else "False" # prints false 

但是,我不確定哪個更加Pythonic。第一種認爲「明確比隱含更好」,但第二種認爲「簡單比複雜更好」。

我還想知道,如果不使用len調用可能會咬我,因爲我正在使用的字典不一定包含字符串,但可能包含其他可用類型(列表,集合等)。 OTOH,前者(帶len調用)如果None被存儲爲值,則代碼將被炸燬,而非len版本將按預期工作(將被評估爲false)。

哪個版本更安全,更多Pythonic?

編輯:澄清假設:我知道關鍵是在字典中,我知道值是可以lenable的。我也無法避免將零長度值輸入詞典。

編輯#2:好像人們錯過了我的問題。我並不想以確定檢查的最Python化/最安全的方式,如果一個關鍵出現在一本字典,我想檢查是否值長度爲零或不

回答

17

如果你知道,關鍵是在字典中,使用

if mydict["key"]: 
    ... 

它操作簡單,易於閱讀,並說,「如果捆綁‘密鑰’的價值評估爲True,有所爲有所不爲」。要知道最重要的珍聞是,容器類型(字典,列表,元組,STR等)只能評估到True如果他們的len大於0

這也將引發KeyError如果你的前提是一個關鍵是在違反了mydict

所有這一切使Pythonic。

+0

..並說:「如果與'key'關聯的值評估爲True,則執行某些操作」 - 但我的意圖是說「如果值的長度不是零」。分裂我想的頭髮。 –

+0

@AdamParkin:嗯。那麼,如果你有一個長度不爲零的物體仍然被評估爲False,那麼這將是非常不尋常的......並且可能會被破壞。另一方面,如果你想防範沒有長度的對象(比如'int's)作爲合法值,那麼檢查'len(value)'就是你所有的東西。但是,除非你有一個很好的理由(例如數據傳輸/存儲等),否則這是一個壞主意。如果你走這條路線,確保你抓住了'TypeError'。 –

13
print (bool(mydict.get('key'))) 

或在一個if語句:

print ('True' if mydict.get('key') else 'False') 

如果不存在的價值是錯誤的情況下(即你希望它在那裏),你應該選擇的解決方案#2,即

print ('True' if mydict['key'] else 'False') 

允許mydict['key']選擇最有效的空白定義。對於某些對象(例如簇中的對象),確定實際長度是相當複雜的操作,而確定對象是否爲空是很簡單的。

您也可以與''比較,即mydict['key'] == '',以使您的表達非常清晰。使用len的作品,但並不直觀。

總之,將它留給測試對象來定義它是否爲空並將其轉換爲布爾值。

+1

對不起,爲什麼.get比使用[]訪問更好? –

+3

@AdamParkin - 因爲'[]'可以引發'KeyError','get'不會。 – Nate

+0

這是如何解決我的問題?我正在測試零長度值,而不是測試字典中是否存在密鑰。 –

3

here

在布爾操作的上下文中,以及當表達式通過控制流語句中使用的,下面的值被解釋爲假:FalseNone,所有類型的數字零,並且空字符串和容器(包括字符串,元組,列表,字典,集合和frozensets)。所有其他值都被解釋爲true。

我認爲這是肯定地說,直接評價它是最好的選擇 - 雖然,作爲@phihag說,它的安全使用get代替,因爲它會保護你從KeyError

-1

你的初始條件不符合Python。你爲什麼要存儲一個空值的密鑰?你可以刪除密鑰而不是將其設置爲無?

的Python的方式是檢查是否存在重點與if key in dictionary,不檢查非空值。

+1

我不是檢查關鍵存在,而是檢查值的長度。雖然我同意「空」的值不是特別的Pythonic,但它是不可避免的問題領域(它是基於對我的程序的輸入,這是我的控制之外的)。我可以在事實之後對字典進行過濾,並刪除鍵值爲空的鍵對,但這需要我詢問的代碼。 –

+3

關於存儲具有空容器值的鍵或任何其他False值沒有任何不合理之處。 –

0

最Python的方式將是沒有定義的未定義的值(儘管這是否可用取決於你使用它的東西),並使用in

mydict = {"key" : "value"} 
print "True" if "key" in mydict else "False" # prints true 
print "True" if "emptykey" in mydict else "False" # prints false 

否則,你有三種選擇:

  1. 使用mydict.get。如果密鑰可能存在或可能不存在於字典中,則應該使用它。
  2. 使用mydict[key]。如果你確定你想要的密鑰在字典中,你應該使用它。使用len(mydict[key]) > 0。這僅適用於定義了__len__的值。通常情況下,集裝箱價值的真值取決於__len__,所以上述情況更可取。
+0

我確信關鍵在於字典,我知道價值觀是可以寬容的。雖然我沒有在這個解決方案中看到真正的答案,但是您是否按照相反的首選順序來推薦這3個答案? –

+0

答案取決於你的具體情況。在你的情況下,使用'mydict [key]'。 Pythonic比使用'len'要好得多。 '如果a:'意味着「如果'a'不是空的:」在Python中如果'a'是一個容器。 – Robin

+1

關於存儲具有空容器值或其他任何假值的密鑰沒有任何不合理之處。 –

1

標題和第一句話居然表示兩個略有不同的問題。

爲標題問題

如果在字典中的值定義

檢查的最Python的方式我會用

"key" in mydict 

去爲第二問題

說我有一本字典,我想檢查一個密鑰是否映射到一個非空值。

我會去與

"key" in mydict and bool(mydict["key"]) 

其中的檢查,看看是否「鑰匙」的第一部分是目前在mydict,第二部分用於再假的「鑰匙」以外的值返回true ,無,空字符串,空字典,空列表和0

+0

同樣,我正在測試字典中的*值*,而不是密鑰。 –

0

你的兩個例子我傾向於第二種。

不過,我建議對存儲空鍵。另外一個defaultdict將工作做好的位置:

>>> from collections import defaultdict 
>>> d = defaultdict(list) 
>>> d[1].append(1) 
>>> 1 in d 
True 

如果您必須存儲空鍵,你不需要字符串值"True""False"。只是這樣做:

print bool(mydict[key]) 
+0

這是檢查的關鍵1,而不是值1。正如我澄清的假設中提到的,避免零len *值*是不可避免的 –

+0

@亞當:我懷疑它是否真的是不可避免的。這感覺就像是濫用字典來存儲空密鑰。另外,我的回答的第二部分是建議,而不是處方。 –

+2

爲什麼你建議不要存儲空鍵?通過這樣做,你正在丟棄信息。 「這把鑰匙被看見,但沒有價值」可能與「從未見過這把鑰匙」有潛在的不同。 –

2

我會使用第一個選項的變化:

>>> mydict = {"key" : "value", "emptykey" : ""} 
>>> print bool(mydict["key"]) 
True 
>>> print bool(mydict["emptykey"]) 
False 

提供__len__任何類都可以被轉換成一個布爾直接(見Truth Value Testing),所以bool(container)是相當於bool(len(container))。長度爲0將成爲布爾型False,而所有其他長度將爲True。你永遠不會有一個負長度的對象。另外,可以通過print直接打印布爾型號爲TrueFalse,因此您不需要條件式。

+0

使用'len'而不是'mydict [「key」]''不* Pythonic。 –

+0

沒有意識到bool(container)和bool(len(container))是等價的語句。更新後的文章以反映。 – Nathan

+0

更改了我的投票。 –

相關問題