2014-01-27 43 views
4

此問題與我的接近,但不是很完美:List minimum in Python with None?。我需要允許列表中所有值的可能性爲None。Python中不是無數的最小值

我有一種情況,我必須在數據庫中查找一些數字,它們可能存在或返回爲空。我需要找到現有數字的最小值。例如:

min_if_exists(1, 2) returns 1 
min_if_exists(5, None) returns 5 
min_if_exists(None, None) returns None 

幸運的是我可以做這樣的事情:

def min_if_exists(a, b): 
    return min(a, b) 
elif a: 
    return a 
elif b: 
    return b 
else: 
    return None 

以下是問題的答案上面提到的:

lowest = min(x for x in (a, b) if x is not None) 

有了這一點,但是,如果和b是None,因爲我輸入了一個空序列,所以我得到一個異常。我可以簡單地理解這個例外,或者我可以在序列中包含一個任意大的數字(a,b,100000000)。對於一個任意長的數字序列都可能沒有,我可以(大概)未Pythonically做到這一點:

def min_if_exists(list_of_nums): 
    not_a_none_exists = False 
    for n in list_of_nums: 
     if n is not None: 
      not_a_none_exists = True 
    if not_a_none_exists: 
     return min(x for x in list_of_nums if x is not None) 
    else: 
     return None 

是否有這樣做的更Python,更簡潔的方式?

+1

您忽略了很快捕獲異常的選項。在我看來,這將是一種Pythonic的做法,考慮到一般的哲學:「最好是做和乞求寬恕而不是要求許可」。 – icktoofay

回答

7

試試這個,這是一個Python的解決方案:

def min_if_exists(list_of_nums): 
    try: 
     return min(x for x in list_of_nums if x is not None) 
    except ValueError: 
     return None 

記住:在Python中,它更容易請求原諒比許可!引用的documentation

這種常見的Python編碼風格假定存在有效的鍵或屬性,並捕獲異常如果假設證明是錯誤的。這種乾淨而快速的風格的特點是存在許多嘗試和除外聲明。該技術與LBYL(三思而後行)常見的許多其他語言的風格形成鮮明對比,如C.

+1

我個人不喜歡這種方法有兩個原因:我必須記住或查找異常名稱('Exception Exception'是不可接受的),第二個原因只是輸入更多。在某些情況下,請求寬恕看起來更清潔,但在這種情況下不會。但這是品味的問題。 – Andrey

+0

當你應該編寫會經常引發異常的代碼(假如你處理它),是否有一個通用的經驗法則?就像它是最短的解決方案(用代碼行來衡量)一樣?我可以看到在某些情況下捕捉異常是如何失控的,例如可能會拋出一些異常。在這種情況下,我認爲我必須同意你的觀點,即簡單地捕捉異常是最乾淨的方式。 –

+0

@JosephKriefall我想不出一個經驗法則。當你覺得這樣做會簡化代碼時,捕獲控制流的異常 - 如果我們要驗證每個可能導致異常並處理它的情況,那麼代碼很快就會變得很笨重 –

1

我認爲基於異常處理的答案由奧斯卡·洛佩茲是一個非常好的選擇。這是另一種(可能是劣質)之一:

def my_min(lst): 
    if lst == [None]*len(lst): 
     return None 
    else: 
     return min(x for x in lst if x is not None) 

print(my_min([0,2,-1]))   # -1 
print(my_min([0,2,None]))   # 0 
print(my_min([None, None, None])) # None 
3

如果您等待的Python 3.4,你可以這樣做很乾淨爲minmax將增長默認的參數(見問題#18111):

>>> def min_not_none(seq): 
...  return min((x for x in seq if x is not None), default=None) 
... 
>>> print(min_not_none([3,None,1])) 
1 
>>> print(min_not_none([None])) 
None 
相關問題