2009-10-12 89 views
3

我有一個相當複雜的對象(反序列化json,所以我沒有太多的控制權),我需要檢查是否存在並遍歷相當深的元素,所以現在我有這樣的東西:有沒有更清晰的方式來鏈接Python中的空列表檢查?

if a.get("key") and a["key"][0] and a["key"][0][0] : 
    for b in a["key"][0][0] : 
     #Do something 

它的工作原理,但相當醜陋。看來必須有更好的方法來做到這一點,那麼更優雅的解決方案是什麼?

回答

14
try: 
    bs = a["key"][0][0] 
# Note: the syntax for catching exceptions is different in old versions 
# of Python. Use whichever one of these lines is appropriate to your version. 
except KeyError, IndexError, TypeError: # Python 3 
except (KeyError, IndexError, TypeError): # Python 2 
    bs = [] 
for b in bs: 

你可以打包成一個功能,如果你不介意再行:

def maybe_list(f): 
    try: 
    return f() 
    except KeyError, IndexError, TypeError: 
    return [] 

for b in maybe_list(lambda: a["key"][0][0]): 
+2

良好的通話,忘記了Python的理念是更好地請求原諒比許可。從.NET開始,儘量避免出現儘可能多的異常,需要一段時間才能習慣。 – Davy8 2009-10-12 01:37:57

+1

你的代碼中有一個錯誤:除了(KeyError,IndexError):',除了KeyError,IndexError:'外,請更改'。否則,它將只捕獲'KeyError'並將其存儲在'IndexError'變量中。 – 2009-10-12 07:07:33

+0

另外,你需要捕獲'TypeError',如果'bs ['key']'包含非序列的東西,就會拋出'TypeError'。 – 2009-10-12 08:05:42

2

這個怎麼樣:

try: 
    for b in a['key'][0][0]: 
     # do stuff. 
except KeyError, TypeError, IndexError: 
    # respond appropriately. 
+0

這也可以從「做東西」中發現異常,而不僅僅是查找列表。 – 2009-10-12 01:33:13

+0

它們應該在'do stuff'塊中用自己的'try/except'語句處理。 – Peter 2009-10-12 01:34:32

+0

除非你不想處理這些。 – recursive 2009-10-12 01:39:31

3

我會寫一個自定義的索引功能如下:

def safe_indexer(obj, *indices): 
    for idx in indices: 
     if not obj: break 

     if hasattr(obj, "get"): 
      obj = obj.get(idx) 
     else: 
      obj = obj[idx] 

    return obj 

用法:

a = {"key": {0: {0: "foo"} } }; 
print safe_indexer(a, "key", 0, 0) 
print safe_indexer(a, "bad", 0, 0) 

輸出:

foo 
None 
+0

嗯,我喜歡這個。如果我發現我經常遇到這種模式,我可能會使用它。現在我只需要一次性的東西,所以約翰的更簡單。 – Davy8 2009-10-12 01:43:34

+0

快速的問題,對Python來說是新的,索引前的*是什麼意思? – Davy8 2009-10-12 01:44:30

+1

這意味着它是一個參數列表。換句話說,所有後續的參數都被合併到一個名爲「indices」的列表中。這樣你就不必明確地傳遞一個列表。相反,直接使用索引作爲safe_indexer的參數。 – recursive 2009-10-12 02:25:21

相關問題