本篇文章起源于StackOverflow上一個熱度非常高的問題:
@Ray Vega (提問者)
舉例說明,現在我得到了如下代碼:
a = []
我如何該檢查 a 是否為空?
面對這個問題,各路高手給出了不盡相同的回答。
最高票答案十分簡潔:
@Patrick (答題者)
if not a:
print("List is empty")
利用空清單的隐式布爾值是一個非常Pythonic的方式。
排名第二的答案與第一觀點相同,并以PEP 8作為依據,說明不僅是清單,Python中的内置序列類型都有推薦的做法:
@Harley Holcombe (答題者)
PEP 8 風格指南 給出了推薦的Pythonic的方法(其中Yes 表示推薦, No表示不推薦):
對序列資料類型(字元串,清單,元組),利用空清單隐式為False的事實
Yes: if not seq:
if seq:
No: if len(seq):
if not len(seq):
然而,排名第三的答案給出了不同的看法:
我更推薦顯式的方法:
if len(li) == 0:
print('the list is empty')
這種方式明确聲明了li是一個序列類型的變量,并且我們是在檢查它的長度。而if not li的問題在于,它會給我li是一個布爾類型變量的印象。
那麼,判斷清單(序列)是否為空的正确姿勢到底是什麼呢?這貌似隻是一個編碼風格的問題,但我們分别從兩類不同看法的出發點挖掘更深層次的原因,可以讓自己更明确地選擇适合自己的風格。
什麼是PEP 8
PEP,全稱Python Enhancement Proposals (翻譯過來就是Python增強建議書),有興趣的讀者可以直接閱覽PEP原文。 PEP本質上是一份Python的官方文檔庫,給Python社群提供資訊,或者描述Python的新特性或開發進展。而PEP 8是這個文檔庫中的一員,專門用于描述Python的編碼規範,這裡規範是指官方推薦的,被認為是更符合Python設計哲學的各種實踐。
同樣實作相同的功能,不同程式設計語言的傾向于使用不同的風格,這是因為每種語言都有自身的設計目的,而Python的設計目的非常明顯:優雅,簡單,可讀。正如PEP 20(另一份PEP)Python之禅中所說:
簡單優于複雜
于是,依據序列長度是否為0将序其隐式轉化為布爾值,成為Python實作中的特性之一,并成為官方推薦的判斷序列是否為空的Pythonic方式。
關于Python是如何做到序列類型乃至所有類型到布爾值的隐式轉化的,我會專門就此問題寫文讨論,歡迎關注。
什麼是動态類型
那麼為什麼還會有人提出明确使用看上去複雜的if len(li) == 0來判斷,并且還有很多人表示贊同呢?這其實來源于Python語言的動态類型特性。
關于什麼是動态類型,我也會另外專門讨論,在這裡,我們隻需闡明,動态類型帶來了一個弊端,我們無法對變量在程式中某一位置的類型進行準确判斷。在閱讀Python代碼的過程中,我們可能最為頭痛的問題就是:這裡這個變量是什麼(類型)???唯一留給我們的線索也許隻有變量名了。而在靜态類型語言,如Java中,一個變量的類型從其聲明時是确定的,在程式中不會發生改變。
回到我們的問題,if not li,看到這段代碼的程式猿可能會疑惑,這裡的li變量是什麼,是一個布爾類型?還是一個整型?這裡的測試是在幹什麼?而if len(li) == 0可以很大程度上進行提示:這大抵是個容器性質的變量,我們在做的大抵是判斷其元素數量是否為0.
總結
讨論到這裡,我們仍然隻能說,Python中如何判斷一個清單是否為空,是一個與風格和習慣有關的問題,但是深入探究我們發現,風格和習慣不是目的,而是手段,代碼最終是服務于編碼者和閱讀者的,抛開性能問題,隻從可讀性出發,你希望閱讀這份代碼的人接受到的是什麼,是簡單優雅,還是資訊提示,這才是比所謂Pythonic更值得思考的問題。
擷取最新文章更新,歡迎關注我的公衆号: StackOverflow Daily