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

Python 增強提案 (Python Enhancement Proposals)

PEP 729 – 型別治理流程

作者:
Jelle Zijlstra <jelle.zijlstra at gmail.com>, Shantanu Jain <hauntsaninja at gmail.com>
討論於:
Discourse 討論串
狀態:
作用中
類型:
流程
主題:
治理, 型別系統
建立日期:
2023-09-19
公告歷史:
2023-10-04, 2023-09-20
決議:
2023-11-20

目錄

摘要

本 PEP 提議了一種管理 Python 型別系統的新方式:設立一個負責維護與開發 Python 型別系統的理事會(Council)。該理事會將維護一套規範與一致性測試套件,並最初由 Python 指導委員會(Steering Council)任命。

動機

Python 型別系統由 PEP 484 於近十年前創立。現今型別系統已被廣泛使用,型別註解已成為編寫優質且易於維護之 Python 程式碼的重要工具。型別系統進行了許多變更,以涵蓋更多使用場景並提升可用性。目前已出現多種型別檢查器,各具優勢。型別註解語法推動了 Python 生態系中多項重大創新,例如廣受歡迎的 dataclasses 模組、由 Pydantic 等套件提供的執行時期型別檢查與驗證,以及由 mypyc 等工具進行的靜態編譯。

然而,隨著型別系統的成長,目前管理型別系統的方式已顯露出幾個相互關聯的問題。

PEP 是唯一的規範

Python 型別系統最初由一份 PEP(PEP 484)創立,至今對型別系統的變更仍透過 PEP 進行。Python 型別系統的規範(就目前有的而言)由這一系列 PEP 組成。但標準追蹤類 PEP 並非作為活文件或規範,而是作為變更提案。

一個例子或許能說明這個問題。在 PEP 484 引入 typing 模組的同時,PEP 3156 引入了 asyncio 模組,這是另一項對 Python 3 的成功至關重要的重大新功能。自建立以來,兩個模組皆有長足發展,並啟發了核心語言的變更。

然而,asynciotyping 在本質上有個差異:使用 asyncio 的使用者只需與標準程式庫本身互動,而 typing 的使用者還必須考慮外部工具——型別檢查器。Python 語言參考文件涵蓋了 typing 模組中的符號,但並未(也不應該)詳述型別檢查器應如何完整詮釋型別系統。這些內容目前僅存在於 PEP 中。

封裝(packaging)生態系也面臨相同的問題,他們試圖透過維護一套獨立的 PyPA 規範來解決此問題。

演進規範十分困難

因為 PEP 是我們唯一的規範,任何被視為對規範的變更在理論上都需要新的 PEP。但對於小規模的變更來說,這通常太過沉重。有時變更會直接應用在舊的 PEP 上,但這違反了已接受並實作的 PEP 應成為歷史文件而不再被修改的原則。

一些具體範例包括:

  • PEP 484 明確指出 typing.NoReturn 不可用於參數註解。然而,型別檢查器長期以來一直接受這種用法。
  • 一份 2023 年的討論指出,PEP 561 對部分 stub(partial stubs)的描述不明確,且主流型別檢查器並未完全按照規範實作。
  • 廣泛使用的第三方套件 typing_extensions 提供了新型別系統功能的向後移植(backports)。型別檢查器應將此模組中的符號視為與 typing 中的符號相同,但這在任何 PEP 中皆未明確規定。

型別系統規範不足

雖然 PEP 提供了規範,但它們通常不夠精確(有時是有意為之)。隨著型別系統的組合複雜度增加,情況更是如此。

最終導致各個型別檢查器必須自行決定如何處理未定義區域。在型別檢查器進行非正式協調的情況下,這產生了並未明確記載的事實標準,使新人更難進入型別系統。例如:

指導委員會並不適合解決上述問題

指導委員會(SC)的職責範圍涵蓋整個語言,並不適合處理純粹關於型別系統的決策——僅僅是因為他們沒有足夠的時間在處理其他職責的同時處理型別系統的艱深細節。這與指導委員會偶爾使用 PEP 授權機制的原因在精神上是一致的。

背書

本 PEP 獲得了所有主流型別檢查器維護者的背書,包括 Rebecca Chen (pytype)Eric Traut (Pyright),以及 mypy 和 Pyre 的維護者私下給予的支持。

規範

我們提議成立一個新組織:型別委員會(Typing Council)。該組織將負責開發與維護 Python 型別系統,並解決上述問題。

「運作與流程」一節描述了該組織的運作與管理方式。

較為精彩的「專案」一節描述了型別委員會可以引導解決上述問題的方案。

授權範圍

型別委員會的任務是確保 Python 型別系統:

  • 實用 (Useful):型別系統應服務於常見的使用場景。如 PEP 484 所認定,主要使用場景是靜態分析,但還有其他場景,例如執行時期型別檢查、靜態編譯、IDE 支援以及文件編寫。型別委員會在決策時應考慮所有這些使用場景,並對支援未來出現的額外使用場景保持開放態度。
  • 易用 (Usable):型別系統對 Python 開發者而言應該易於使用。編寫能被型別檢查器接受的強型別 Python 程式碼應具備良好的工程體驗(ergonomic)。且型別系統應具備良好的說明文件。
  • 穩定 (Stable):隨著型別系統成熟,使用者應能信賴其已註解型別的程式碼能持續運作,並能對型別系統建立信任的心理模型。變更應謹慎進行,並以最小化破壞為原則。儘管如此,型別系統仍需能夠演進,且對型別檢查器行為採取與 Python 本身相同的相容性準則並不合理。當然,typing 模組中物件的存在與執行時期行為,確實遵循 PEP 387 中的 Python 標準相容性政策。

運作與流程

理事會將有 3 至 5 名成員,由傑出的社群成員組成,例如 Python 核心開發者與主流型別檢查器的維護者。成員應包含與型別檢查相關之各類專案的相關人員,這可能包括型別檢查器、CPython、typeshed 或其他專案。

理事會的首批成員為:

  • Eric Traut (Pyright;PEP 647PEP 681PEP 695 的作者)
  • Guido van Rossum (核心開發者;PEP 484PEP 526 的作者)
  • Jelle Zijlstra (核心開發者;typeshed;pyanalyze;PEP 688PEP 702 的作者)
  • Rebecca Chen (pytype)
  • Shantanu Jain (核心開發者;typeshed;mypy)

理事會目前的成員記錄於 python/typing-council 儲存庫中。

理事會成員沒有任期限制。成員可隨時辭職。預期每位成員在辭職前最多擔任五個連續年度。

若有職缺且尚有三名或更多成員,則由理事會決定是否任命新成員。為確定接替人選,將從型別社群收集提名。允許自薦。現有的型別委員會將隨後從提名者中決定接替成員。預期這將透過自行決定(fiat)來完成,但型別委員會可以選擇任何他們認為合適的方式(包括投票)來選擇接替者。

型別委員會仍需對指導委員會負責。指導委員會可在任何時間、出於任何原因(公開或私下)對型別委員會的組成做出具體變更或提出非具體變更的要求。

我們承認這不是特別民主的結構,並且對型別委員會寄予厚望。然而,Python 社群在非民主結構方面有悠久的成功歷史!我們相信自我管理、成員輪替以及對指導委員會的問責機制,將足以確保型別委員會滿足社群的需求。

理事會主要透過審查 GitHub PR 來運作。定期會議可能不是必要的,但理事會可以設置視訊會議、私人聊天室或任何他們在內部決定的其他機制。

理事會應以透明度為目標,將所有決策公開發布於 discuss.python.org,並盡可能說明理由。在做出決定之前,理事會應給予所有感興趣的社群成員表達意見的機會。從開始討論到理事會做出決定之間,至少應間隔一週。

理事會成員將有資格贊助 PEP。若此 PEP 被接受,則應修正 PEP 1 以註記此事實。

與指導委員會的關係

與現在一樣,Python 指導委員會仍將負責 Python 語言的總體方向,並將繼續對型別相關的 PEP 做出決策。型別委員會將針對型別相關的 PEP 向指導委員會提供書面意見與建議。

然而,型別系統的較小規模變更可由型別委員會直接進行。指導委員會也可以選擇將某些 PEP 的決策授權給型別委員會(如同任何其他 PEP 授權一樣)。

關於在這種模型下如何處理過去與近期問題的一些範例:

  • PEP 695(型別參數語法)這樣改變語言語法的 PEP,需要由指導委員會做出決定;型別委員會僅提供意見或背書。同樣地,像 PEP 702(棄用)這樣的 PEP 將由指導委員會決定,因為它涉及純型別之外的執行時期行為。其他需要由指導委員會決定的範例包括 PEP 718(可下標函式)與 PEP 727(文件中繼資料)。
  • PEP 698 (@override) 這樣僅影響型別檢查器使用者且未改變整體語言的 PEP,預設也會由指導委員會決定。然而,此類 PEP 可授權給型別委員會做出決定(如同任何其他 PEP 授權)。其他可能被授權的 PEP 範例包括 PEP 647(型別防護)、PEP 655(個別必需的 TypedDict 項目)、PEP 673 (Self) 與 PEP 675 (Literal)。
  • 添加較小的功能(例如將 typing.Never 作為 typing.NoReturn 的別名)將透過對規範與一致性測試套件的 PR 來完成。型別委員會將隨後決定是否合併該 PR。如果他們認為有必要,可能會要求在 PEP 中定義並討論該功能。
  • 如果對規範某部分的詮釋產生混淆(如同最近 PEP 561 中的部分 stub 所發生的情況),則某人將對型別規範提出 PR 以釐清規範,隨後型別委員會將對規範變更做出決定。

執行時期的 typing 模組將繼續由 CPython 核心開發團隊維護。然而,任何影響型別檢查器行為的執行時期模組變更,都應在伴隨規範變更(見下文)的情況下進行,並須經型別委員會核准。例如,在 Python 3.11 中,核心開發者加入了新的函式 typing.assert_type()。如果型別委員會已到位,此變更將需要對應的規範變更並經由型別委員會核准。另一方面,Python 3.11 也加入了 typing.get_overloads() 內省輔助函式。由於此函式不影響型別檢查器的行為,因此不需要型別委員會核准。然而,由於對執行時期型別檢查器的支援屬於委員會的職責範圍,他們應監控此類變更並在適當時提供回饋。

與型別檢查器的關係

型別委員會對型別檢查器沒有直接權限;無法強迫它們實作特定功能或進行行為變更。型別檢查器之所以有動力遵循委員會制定的規範,是因為這使它們能夠利用共享資源,例如公開遵循規範之型別資訊的程式庫、typeshed 中的 stub 檔案、typing 標準程式庫模組以及涵蓋標準型別系統的使用者說明文件。型別檢查器可以自由擴充型別系統或偏離規範,但應清楚記錄此類差異。

型別檢查器需要實作型別委員會所做之任何決策這一事實,對委員會起到了一種有益的制衡作用,確保其決策是保守且經過深思熟慮的。個別型別檢查器仍然可以自由地進行創新,成功的創新可以納入標準型別系統中。

專案

以下是型別委員會將負責的工作:

一致性測試套件

一致性測試套件將提供機器可檢查的文件,說明型別檢查器應如何檢查 Python 程式碼,並附上主要型別檢查器實作在測試套件上的結果。Shantanu 建立了一個初步草稿

這將包含來自先前 PEP 所規定行為的規範性測試,以及讓我們記錄現有實作在任何標準皆未規定區域之行為的描述性測試。這些描述對於為下述工作提供資訊以及確定標準化的重點領域非常有用。

型別系統規範

規範將初步透過拼接現有 PEP 中的規範章節來建立,然後逐漸改進以釐清混淆點並涵蓋更多領域。Jelle 建立了這樣一個拼接規範的草案

該規範有幾個受眾:

  • 對於型別檢查器,它提供了理想型別檢查器應如何運作的描述。個別型別檢查器有不同的目標與技術限制,如果它們沒有資源完全實作它,或者認為不同的行為能更好地服務使用者,它們可以自由偏離規範。然而,它們應記錄與規範的此類偏離。
  • 對於 typeshed 或希望與多種型別檢查器相容的程式庫等專案,它提供了一套可以遵循的規則,使程式碼能被型別檢查器理解。
  • 對於希望對型別系統提出變更的人員,它為任何新提案提供了基礎。

值得注意的是,該規範並非針對使用型別的應用程式開發者。此類使用者通常不需要擔心跨型別檢查器的相容性。他們更適合由非正式、面向使用者的參考文件來服務,這將在下一節中討論。

社群內部對於此類規範應具備何種正式程度有不同意見。雖然本文建議採取一種以現有規範為基礎的漸進式方法,但它並不旨在規定最終狀態。型別委員會將提供一種機制,允許規範演進以達到社群所期望的正式程度,例如,透過納入 Kevin Millikin 的 「Python 靜態型別」文件 的部分內容,作為實現更好規範化的手段。

對規範提出的變更(包括 PEP)通常應伴隨以下內容:

  • 獲得型別檢查器維護者的認可,以確認該變更可以在其型別檢查器中實作與維護。
  • 對於現有功能的變更,進行現有型別檢查器行為的調查。如果現有型別檢查器的行為大致相似,這即是應將其共享行為納入規範的一部分的證據。
  • 對一致性測試套件的變更,以展示所規定的行為。

面向使用者的型別系統參考文件

文件對於 Python 型別系統的成功至關重要,因此型別委員會應確保型別系統有良好的說明文件。

如前所述,PEP 是針對多個受眾且難以釐清的特定時間點變更提案。這使得它們不適合作為使用者文件。上一節討論的規範將是一份活文件,但它可能太過技術性,無法作為正常使用的文件。

因此,一份分開的、面向使用者的型別系統參考文件將會很有幫助。這類努力可以擴充 typing.python.org 上的文件,並重複使用來自個別型別檢查器說明文件與 CPython 說明文件的材料。

修訂

本 PEP 作為型別委員會的章程。對其運作的變更可以透過新的 PEP 或本 PEP 的修正案來進行。無論哪種情況,變更皆將由指導委員會在社群討論後決定。

遭否決的想法

從零開始撰寫規範

本 PEP 提議從現有 PEP 開始建立型別規範,然後在必要時釐清並改進規範。部分社群成員更傾向於從零開始,撰寫一套涵蓋整個型別系統的、更正式的新規範。這可以為規範提供更穩固的基礎。

然而,這將是一項大得多的任務。Kevin Millikin 目前的正式化努力是一個很好的開始,但到目前為止僅涵蓋了 PEP 484 的一部分。考慮到 typing.Protocoltyping.Literaltyping.TypedDict 等主要型別系統功能都是在 PEP 484 之後才引入的,涵蓋其餘型別系統可能需要數倍的努力。社群是否具備進行如此龐大任務的精力尚不明確。即使有人站出來完成編寫規範的所有工作,社群成員與型別檢查器維護者仍需投入大量精力來考慮該規範是否準確反映了當前行為,若否,則應變更規範還是型別檢查器。

從現有 PEP 開始會產生品質較低的規範,但這意味著型別委員會可以透過改進與釐清規範,立即開始對型別系統的任何部分產生影響。正式化工作仍然可以透過逐漸替換規範章節的方式進行。

替代性治理機制

本 PEP 的早期草案建議由指導委員會每年任命型別委員會成員。現任指導委員會建議,讓型別委員會自我組織會更好,以避免指導委員會需要持續監督型別委員會。

替代性的治理機制是可能的,包括更民主的機制,但這些機制通常會引發幾個棘手問題,需要更繁瑣的流程,並且可能更具分裂性。例如,參見 PEP 8000 系列,或近期關於其他 Python 子社群中替代性治理的討論。最終,型別委員會在指導委員會的授權下運作,因此可以依靠它來啟動治理並作為問責機制。

不採取行動

我們希望無論此 PEP 是否被接受,在改善型別系統的專案上都能取得實質進展。我們預期像規範或潛在的 PEP 授權這樣的專案會從型別委員會中受益更多,而像最終使用者文件這樣的專案受益較少。毫無疑問,瓶頸可能是貢獻者的努力,而非治理。

然而,目前社群可用來解決潛在爭端的工具,要麼是建立近似的共識,要麼是個別專案或貢獻者行使權力。雖然前者非常有價值,但這是一個緩慢的過程,往往最終導致不採取行動。後者可能導致生態系一致性降低。最後,容易理解的治理結構使社群更具包容性與公平性。

聯絡方式

若要請求型別委員會做出決定,社群成員可以在 python/typing-council 儲存庫中開啟議題(issue)。


來源:https://github.com/python/peps/blob/main/peps/pep-0729.rst

最後修改:2025-03-05 16:28:34 GMT