PEP 457 – 僅限位置引數的表示法
- 作者:
- Larry Hastings <larry at hastings.org>
- 討論至:
- Python-Dev 列表
- 狀態:
- 最終版
- 型別:
- 資訊性
- 建立日期:
- 2013年10月8日
概述
本 PEP 提出了 Python 中僅限位置引數的表示法。僅限位置引數是沒有外部可用名稱的引數;當呼叫接受僅限位置引數的函式時,位置引數僅根據其位置對映到這些引數。
本 PEP 是一個資訊性 PEP,描述了在描述使用僅限位置引數的 API(例如在 Argument Clinic 中,或在 inspect.Signature 物件的字串表示中)時使用的表示法。另一個 PEP,PEP 570,提議將此表示法提升為完整的 Python 語法。
基本原理
Python 始終支援僅限位置引數。Python 的早期版本缺乏按名稱指定引數的概念,所以自然所有引數都是僅限位置的。這種情況在大約 Python 1.0 左右發生了變化,當時所有引數突然變成了位置或關鍵字引數。但是,即使在當前版本的 Python 中,許多 CPython 的“內建”函式仍然只接受僅限位置引數。
用現代 Python 實現的函式可以透過可變引數 *args 引數接受任意數量的僅限位置引數。但是,沒有 Python 語法來指定接受特定數量的僅限位置引數。換句話說,有許多內建函式的簽名無法用 Python 語法表示。
本 PEP 提出了一種用於此類簽名的表示法,它可以構成向後相容語法的基礎,該語法應該允許在純 Python 程式碼中實現任何內建函式(有關該提案,請參閱PEP 570)。
當前 Python 中僅限位置引數的語義
有許多內建函式只接受僅限位置引數。由此產生的語義對於 Python 程式設計師來說很容易體驗到——只需嘗試呼叫其中一個,並透過名稱指定其引數即可。
>>> pow(x=5, y=3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: pow() takes no keyword arguments
此外,還有一些函式具有特別有趣的語義。
range(),它接受一個在其所需引數*左側*的可選引數。[2]dict(),其對映/迭代器引數是可選的,並且在語義上必須是僅限位置的。此引數的任何外部可見名稱都會遮蔽該名稱進入**kwarg關鍵字可變引數字典![1]
顯然,可以透過接受 (*args, **kwargs) 並手動解析引數,在純 Python 程式碼中模擬其中任何一個。但這會導致 Python 函式的簽名與其實際接受的引數之間出現脫節,更不用說實現所述引數解析的工作了。
動機
本 PEP 不建議我們在 Python 中實現僅限位置引數。本 PEP 的目標只是定義語法,以便
- 文件可以清晰、明確、一致地表達函式的引數將如何解釋。
- 該語法保留供將來使用,以防社群某天決定將僅限位置引數新增到語言中。
- Argument Clinic 可以使用該語法的一種變體作為其輸入的一部分,用於定義內建函式的引數。
僅限位置引數文件的現狀
僅限位置引數的文件不完整且不一致。
還有一個重要的想法需要考慮:目前在文件中無法判斷函式是否接受僅限位置引數。open() 接受關鍵字引數,ord() 不接受,但僅僅透過閱讀文件無法判斷這是真的。
語法和語義
從“萬米高空”來看,暫時忽略 *args 和 **kwargs,函式定義的語法目前看起來像這樣。
def name(positional_or_keyword_parameters, *, keyword_only_parameters):
基於這種觀點,函式的新語法將如下所示。
def name(positional_only_parameters, /, positional_or_keyword_parameters,
*, keyword_only_parameters):
/ 之前的所有引數都是僅限位置的。如果函式簽名中未指定 /,則該函式不接受任何僅限位置引數。
僅限位置引數可以有預設值,如果有預設值,則它們是可選的。沒有預設值的僅限位置引數是“必需”的僅限位置引數。
僅限位置引數的更多語義
- 儘管僅限位置引數在技術上具有名稱,但這些名稱僅供內部使用;僅限位置引數*絕不能*透過名稱進行外部定址。(類似於
*args和**kwargs。) - 如果
/之後有引數,則必須在/之後指定一個逗號,就像在表示轉換為僅限關鍵字引數的*之後有一個逗號一樣。 - 此語法對
*args或**kwargs沒有影響。
其他限制
Argument Clinic 使用這種語法的一種形式來指定內建函式。它施加了理論上不必要但使實現更容易的進一步限制。具體來說:
- 具有僅限位置引數的函式目前不能具有任何其他型別的引數。(這在不久的將來可能會稍微放寬。)
- Argument Clinic 支援一種稱為“可選組”的附加語法。“可選組”是一組順序的僅限位置引數,它們必須作為一個組被指定或不被指定。例如,如果在 Argument Clinic 中定義了一個接受四個引數的函式,並且所有引數都是僅限位置的並且屬於一個可選組,那麼在呼叫函式時必須指定零個引數或四個引數。這對於覆蓋更多的 Python 遺留庫是必要的,但超出了本 PEP 的範圍,不建議實際包含在 Python 語言中。
未來實現者的注意事項
如果我們決定在未來版本的 Python 中實現僅限位置引數,我們將不得不做一些額外的工作來保留它們的語義。問題是:當函式被呼叫時,我們如何通知引數沒有為其傳遞任何值?
顯而易見的解決方案是:向 Python 新增一個新的單例常量,當引數未對映到引數時傳遞該常量。我建議將該值命名為 undefined,並將其作為名為 Undefined 的特殊類的單例。如果僅限位置引數在呼叫時未接收到引數,則其值將設定為 undefined。
但這又引出了一個問題。我們如何區分“此僅限位置引數未接收到引數”和“呼叫者為此引數傳入了 undefined”?
禁止將 undefined 作為引數傳遞給函式(例如,引發異常)會很好。但這會降低 Python 的速度,而且“同意的成年人”規則在這裡似乎適用。因此,禁止它可能應該受到強烈勸阻,但不應完全阻止。
但是,應該允許(並鼓勵)使用者函式將 undefined 指定為引數的預設值。
未解決的問題
Python 中有三種類型的引數:
- 僅限位置引數,
- 位置或關鍵字引數,以及
- 僅限關鍵字引數。
Python 允許函式同時具有 2 和 3。而一些內建函式(例如 range)同時具有 1 和 3。那麼同時具有 1 和 2 的函式有意義嗎?或者以上所有型別?
致謝
將“/”用作僅限位置引數和位置或關鍵字引數之間分隔符的功勞歸於 Guido van Rossum,這是他 2012 年的一項提案。[6]
將左側選項組賦予更高優先順序的功勞歸於 Alyssa Coghlan。(2013 年在美國 PyCon 上的面對面交流。)
版權
本文件已置於公共領域。
來源:https://github.com/python/peps/blob/main/peps/pep-0457.rst
最後修改時間:2025-02-01 08:59:27 GMT