idioms Python成語返回第一項或None
我確信有一個更簡單的方法可以做到這一點,這對我來說不會發生。
我打電話給一堆返回列表的方法。 該列表可能為空。 如果列表非空,我想返回第一個項目; 否則,我想返回None。 此代碼有效:
my_list = get_list()
if len(my_list) > 0: return my_list[0]
return None
在我看來,做這件事應該有一個簡單的一行成語,但對於我來說,我想不起來。 在那兒?
編輯:
我在這裡尋找單行表達的原因並不是我喜歡難以置信的簡潔代碼,而是因為我不得不編寫如下這樣的代碼:
x = get_first_list()
if x:
# do something with x[0]
# inevitably forget the [0] part, and have a bug to fix
y = get_second_list()
if y:
# do something with y[0]
# inevitably forget the [0] part AGAIN, and have another bug to fix
我想要做的事情當然可以用一個函數來完成(可能會):
def first_item(list_or_none):
if list_or_none: return list_or_none[0]
x = first_item(get_first_list())
if x:
# do something with x
y = first_item(get_second_list())
if y:
# do something with y
我發布了這個問題,因為我經常被Python中簡單的表達式所能做到的事情感到驚訝,我認為編寫一個函數是一件很愚蠢的事情,如果有一個簡單的表達式可以做到這一點。 但看到這些答案,這似乎是一個簡單的解決方案。
最常用的python慣用方法是在迭代器上使用next(),因為列表是可迭代的 。 就像@JFSebastian在2011年12月13日的評論中所說的那樣。
next(iter(the_list), None)
如果the_list
為空,則返回None。 請參閱下一個()Python 2.6+
或者如果你確定the_list
不是空的:
iter(the_list).next()
請參閱iterator.next()Python 2.2+
如果你發現自己試圖從列表理解中抽取第一件事物(或無),你可以切換到一個生成器來執行它,如:
next((x for x in blah if cond), None)
Pro:如果blah不是可編譯的,則可以工作。Con:這是不熟悉的語法。 雖然在ipython中進行黑客入侵和過濾,但這很有用。
對於它而言,這是另一種可能性。
return None if not get_list() else get_list()[0]
好處:此方法處理get_list為None的情況,不使用try / except或assignment。 據我所知,上述的實現都不能處理這種可能性
垮台:get_list()被調用兩次,這是非常不必要的,特別是當列表很長時和/或在函數被調用時創建。
事實是,在我看來,更多的是“Pythonic”,它提供的代碼是可讀的,而不僅僅是因為你可以製作一行代碼:)我不得不承認,我多次因為不必要地壓縮Python代碼而感到內疚,我很感動,我可以做一個複雜的功能看起來很小:)
編輯:正如用戶“hasen j”在下面評論的那樣,上面的條件表達式在Python 2.5中是新的,如下所述: https://docs.python.org/whatsnew/2.5.html#pep-308 : https://docs.python.org/whatsnew/2.5.html#pep-308 。 謝謝,哈森!
坦率地說,我認為沒有更好的成語:你的語言清晰簡潔 - 不需要任何“更好”的東西。 也許吧,但是這真的是一個有趣的問題,你可以改變, if len(list) > 0:
with if list:
- 一個空列表將總是評估為False。
在相關說明中,Python 不是 Perl(不是雙關語!),您不必獲得最酷的代碼。
實際上,我在Python中看到的最糟糕的代碼也非常酷:-)並且完全無法維護。
順便說一下,我在這裡看到的大多數解決方案在列表[0]評估為False時(例如空字符串或零)沒有考慮到 - 在這種情況下,它們都返回None而不是正確的元素。
def head(iterable):
try:
return iter(iterable).next()
except StopIteration:
return None
print head(xrange(42, 1000) # 42
print head([]) # None
順便說一句:我會重新將您的一般程序流程改為如下所示:
lists = [
["first", "list"],
["second", "list"],
["third", "list"]
]
def do_something(element):
if not element:
return
else:
# do something
pass
for li in lists:
do_something(head(li))
(盡可能避免重複)
這個怎麼樣:
(my_list and my_list[0]) or None
注意:對於對象列表,這應該可以正常工作,但是如果按照下面的註釋編號或字符串列表,它可能會返回錯誤的答案。
try:
return a[0]
except IndexError:
return None
那麼怎麼樣: next(iter(get_list()), None)
? 可能不是這裡最快的,但是標準(從Python 2.6開始)和簡潔。
我的用例只是設置局部變量的值。
我個人發現嘗試和除了風格清潔劑閱讀
items = [10, 20]
try: first_item = items[0]
except IndexError: first_item = None
print first_item
比切分列表。
items = [10, 20]
first_item = (items[:1] or [None, ])[0]
print first_item
有幾個人建議做這樣的事情:
list = get_list()
return list and list[0] or None
這在很多情況下都有效,但只有在list [0]不等於0,False或空字符串的情況下它才會起作用。 如果list [0]為0,False或空字符串,則該方法將錯誤地返回None。
我在自己的代碼中創建了這個bug太多次了!