Python 有一項預設的做法,很多程式設計語言都沒有——它的所有函數都會有一個傳回值,不管你有沒有寫 return 語句。
本文出自“Python為什麼”系列,在正式開始之前,我們就用之前讨論過的 pass語句 和 ...對象 作為例子,看看 Python 的函數是怎樣“無中生有”的:
可以看出,我們定義的兩個函數都沒有寫任何的 return 語句,但是在函數調用後,都能取到一個傳回值。
它們的執行效果跟直接寫 return 語句相比,是完全相同的:
這 4 個例子屬于兩種類型:一種沒有寫 return,但是都有隐藏的 return 傳回值;一種寫了 return,而且實際也有傳回值。
也就是說,後者在語義和行為上表現一緻,前者雖然在語義上缺失,但是卻有實際的行為和結果;後者的行為是顯性的,前者卻是隐性的。
《Python之禅》中有一句“顯性勝于隐性(Explicit is better than implicit)”,但是,出于簡潔和便利的考慮(Simple is better than complex),實際上 Python 中有很多行為都是隐性的,會把一些在文法層面的事交給解釋器去完成。
上一期的 真值判斷 是隐性的行為,本文前兩個例子也是如此。
使用
dis
檢視位元組碼,就可以看到其背後的小動作:
在這個對比圖中,可以看出上述 4 個函數的解釋器指令一模一樣!
不管有沒有寫 return,它們都會執行 return 的邏輯,而且預設的傳回值就是 None。
那麼,問題來了:Python 的函數為什麼能預設傳回 None 呢?它是如何實作的呢?
答案就在解釋器中,當 CPython 解釋器執行到函數的最後一個代碼塊時,若發現沒有傳回值,它就會主動地加上一個 Py_None 值傳回(出自:compile.c):
也就是說,如果定義的函數沒有傳回值,Python 解釋器就會(強行地)預設給我們注入一段傳回邏輯!
對于解釋器的這種附贈的服務,大家是覺得很貼心,還是嫌棄它多事呢?
這樣的做法似乎沒多少好處,但似乎也沒有壞處?
那麼,這就會引出新的問題:Python 為什麼要求函數都要有傳回值呢?為什麼它不像某些語言那樣,提供一個 void 關鍵字,支援定義無傳回值的空函數呢?
關于這個問題,我們将在下一期“Python為什麼”系列文章中揭曉。
如果你覺得這些問題很有啟發性,那你應該會喜歡這些文章:
1、Python為什麼使用縮進來劃分代碼塊?
2、Python 的縮進是不是反人類的設計?
3、Python 為什麼不用分号作語句終止符?
4、Python 為什麼沒有 main 函數?為什麼我不推薦寫 main 函數?
5、Python 為什麼推薦蛇形命名法?
6、Python 為什麼不支援 i++ 自增文法,不提供 ++ 操作符?
7、Python 為什麼隻需一條語句“a,b=b,a”,就能直接交換兩個變量?
8、Python 為什麼用 # 号作注釋符?
9、Python 為什麼要有 pass 語句?
10、Python 為什麼會有個奇怪的“...”對象?
11、Python 為什麼能支援任意的真值判斷?
本文屬于“Python為什麼”系列(Python貓出品),該系列主要關注 Python 的文法、設計和發展等話題,以一個個“為什麼”式的問題為切入點,試着展現 Python 的迷人魅力。所有文章将會歸檔在 Github 上,項目位址:https://github.com/chinesehuazhou/python-whydo