Python 為什么沒有 void 關鍵字?
void 是編程語言中很常見的關鍵字之一,從字面上理解,它是“空的、空集、空白”的意思,最常用于表示函數(shù)的一種返回值類型。
維基百科上有一個定義:
The void type, in several programming languages derived from C and Algol68, is the type for the result of a function that returns normally, but does not provide a result value to its caller.
在 C、Algol68 及它們所派生的幾種編程語言中,void 類型是函數(shù)正常返回的一種類型,但是不會給調用者返回一個值。
簡單來說,void 是一種類型(type),但是沒有具體的值(value)。
這到底是什么意思呢?
以 Python 的幾種常見類型為例,我們可以從對比中看出規(guī)律:int 是一種表示整數(shù)的類型,它有無限個可能的整數(shù)值;bool 是一種布爾類型,它有兩個可能的值(True 和 False);NoneType 是一種表示 None 的類型,它只有一個值(None)。
至于 void,它是一種更為抽象的特殊類型,但是不包含任何值。
介紹完概念上的含義,我們就可以進入正題了。標題中的問題可以進一步分解成兩個:
- 其它語言為什么要使用 void 關鍵字?
- Python 為什么不設計出 void 關鍵字?
對于第一個問題,我們以 C/C++ 為例,先看看 void 的兩種使用場景(PS:此處只考慮函數(shù)的用法,不考慮指針的用法,因為 Python 沒有指針):
當 void 用在函數(shù)的參數(shù)位置時,它表示該函數(shù)不需要傳參。
最初 C 語言的f() 表示參數(shù)數(shù)量不確定,為了另外表達“不需要參數(shù)”的語義,所以引入f(void) 作為限定。后來的語言(包括 Python)基本不在參數(shù)中使用 void,而是直接用f() 表示不需傳參。C++ 為了兼容 C,所以才同時支持這兩種語法。
當 void 用在函數(shù)前作修飾時,它表示該函數(shù)沒有返回值。
在 C 語言中,若不聲明返回類型,則f() 函數(shù)在編譯后會返回整型的值。為了避免混亂,當不需要返回值時,就使用void f() 來作限定。
同時,更主要的是,它還起到了占位符的作用,表明一個函數(shù)的類型是已知的,這對代碼可讀性和編譯都有所幫助。
void 作為函數(shù)的空返回值類型,這種用法在 C++/Java 中也被繼承了。另外,在 Javascript 中也有 void 的身影,只不過它成了一種操作符,起到了完全不同的作用,此處不表。
但是,Python 從頭到尾都沒有 void 關鍵字。
為什么會這樣?難道是因為在 Python 中不存在其它語言所面對的問題么?還是說,Python 中有自己的一套解決方案?
仍以跟函數(shù)相關的兩種用法為例作分析吧。
在表示函數(shù)不需傳參時,f(void)這種寫法根本就是多余的,所以 Python 使用了最簡單明了的無參式寫法f()。
至于返回值類型的用法,在我們定義出一個函數(shù)時,例如最簡單的def func():pass ,為了讓它的調用結果func() 是一個合法的對象,那它必須具有一個有效的類型(type)。
這應該是以類型為基的編程語言都會遇到的共性問題,Python 也不例外。
這個時候,如果函數(shù)本身沒有顯式地 return 出一個對象的話,就有兩種可能的解決辦法:
- 方法一,即聲明該函數(shù)為 void 類型,像 C 和其它語言所做的那樣,只要能通過類型檢查即可
- 方法二,則是 Python 所用的方法,即令解釋器隱式地返回一個 None 對象,也就是令函數(shù)默認得到一個 NoneType 類型,再用于類型檢查(PS:Javascript 也類似,只不過它默認返回的是 undefined,它不是一個對象,而是一種表示“未定義”的類型,類似于 void)
簡單而言,Python 的設計思路是直接復用已有的 NoneType 類型,并讓解釋器來填補缺失掉的函數(shù)類型。
關于 Python 解釋器的這個隱式填補過程,我已在上一篇《Python 函數(shù)為什么會默認返回 None?》文章詳細分析過,感興趣的同學可去查閱。
這樣做的好處至少有兩點:一是沒有引入新的 void 類型和關鍵字;二是不需要程序員在函數(shù)前聲明返回類型,這就跟有顯式返回值的寫法保持了一致。
試想一下,如果 Python 不讓函數(shù)默認有返回值的話,就可能要寫成 void def func():... 這樣的形式,那它就變成了函數(shù)定義時的一種特例。與另一種特例函數(shù)相比,即異步函數(shù)asyc def func():... ,就可能引起混亂。
總體而言,Python 似乎認為 void 空類型不是那么有存在的必要,似乎 NoneType 類型就足夠了,而當缺少返回值時,讓解釋器統(tǒng)一注入是極為方便的,因此才出現(xiàn)了我們看到的現(xiàn)狀。
至此,文章標題的問題算是圓滿回答了。
最后,讓我們開始進入 ending 吧:本文明面上是以“Python 為什么沒有 void 關鍵字”為切入點,然而,它實際上瞄準的卻是“Python 為什么需要返回 None”的問題。
在《Python 函數(shù)為什么會默認返回 None?》這篇文章中,我介紹了 Python 中函數(shù)默認返回 None 的機制,它是屬于“how can”的內容。但是為什么要默認返回 None 呢?這則是屬于“why need”或者“why should”的問題,而它需要從 void 關鍵字的缺失開始談起……
那么,為什么 Python 沒有 void 關鍵字呢?請往上翻,重新閱讀本文……
本文屬于“Python為什么”系列(Python貓出品),該系列主要關注 Python 的語法、設計和發(fā)展等話題,以一個個“為什么”式的問題為切入點,試著展現(xiàn) Python 的迷人魅力。所有文章將會歸檔在 Github 上,項目地址:https://github.com/chinesehuazhou/python-whydo