Following system colour scheme - Python 增強提案 Selected dark colour scheme - Python 增強提案 Selected light colour scheme - Python 增強提案

Python 增強提案

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 可以使用該語法的一種變體作為其輸入的一部分,用於定義內建函式的引數。

僅限位置引數文件的現狀

僅限位置引數的文件不完整且不一致。

  • 有些函式透過將可選的僅限位置引數*組*括在巢狀的方括號中來表示。[3]
  • 有些函式透過呈現具有不同引數數量的多個原型來表示可選的僅限位置引數組。[4]
  • 有些函式使用上述兩種方法。[2] [5]

還有一個重要的想法需要考慮:目前在文件中無法判斷函式是否接受僅限位置引數。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 中有三種類型的引數:

  1. 僅限位置引數,
  2. 位置或關鍵字引數,以及
  3. 僅限關鍵字引數。

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