天天看點

快10-60%!Python3.11來了!

編輯:陳萍、杜偉

想要體驗新功能的小夥伴趕緊去試試新版本吧!

終于,Python 3.11 正式版釋出了!

快10-60%!Python3.11來了!

2020 年 1 月 1 日,Python 官方結束了對 Python 2 的維護,這意味着 Python 2 已完全退休,進入了 Python 3 時代。打從進入 3 版本以來,Python 官方已經釋出了衆多修改分支,現在來到了最新的版本 Python 3.11。

其實研究界有個不公開的秘密,那就是 Python 運作速度并不快但容易上手,是以使用人數超級多,在衆多最受歡迎語言榜單中 Python 多次位列第一。很多開發者都期待這門語言的性能有所提升,還有人暢想 Python 4 會不會在某個不經意的時刻到來,有這種想法的人可以放一放了,Python 之父 Van Rossum 都說了,Python 4.0 可能不會來了。

Van Rossum 曾表示:「我和 Python 核心開發團隊的成員對 Python 4.0 沒什麼想法,提不起興趣,估計至少會一直編号到 3.33。Python 的加速是漸進式的,3.11 版本會有新的速度提升,預計會比 3.10 快得多。」

正如 Van Rossum 所說,根據官方資料顯示最新釋出的 Python 3.11 比 Python 3.10 快 10-60%,對使用者更友好。這一版本曆經 17 個月的開發,現在公開可用。

Python 3.11 的具體改進主要表現在:更詳實的 Error Tracebacks、更快的代碼執行、更好的異步任務文法、改進類型變量、支援 TOML 配置解析以及一些其他非常酷的功能(包括快速啟動、Zero-Cost 異常處理、異常組等)。

快10-60%!Python3.11來了!

Python 指導委員會成員和核心開發者、Python3.10/3.11 釋出管理者 Pablo Galindo Salgado 表示,為了使 3.11 成為最好的 Python 版本,我們付出了很多努力。

快10-60%!Python3.11來了!

Python 3.11 新特性

Error Tracebacks

Python 這門程式設計語言對初學者非常友好,它具有易于了解的文法和強大的資料結構。但對于剛剛接觸 Python 的人來說卻存在一個難題,即如何解釋當 Python 遇到錯誤時顯示的 traceback。

Python 3.11 将 Decorative annotation 添加到 tracebacks 中,以幫助使用者更快地解釋錯誤消息。想要獲得這種功能,可以将以下代碼添加到 inverse.py 檔案中。

快10-60%!Python3.11來了!

舉例來說,你可以使用 inverse() 來計算一個數的倒數。因為 0 沒有倒數,是以在運作下列代碼時會抛出一個錯誤。

快10-60%!Python3.11來了!

注意嵌入在 traceback 中的 ^ 和~ 符号,它們指向導緻錯誤的代碼。與此前的 tracebacks 一樣,你應該從底層開始,然後逐漸向上。這種操作對發現錯誤非常有用,但如果代碼過于複雜,帶注釋的 tracebacks 會更好。

更快的代碼執行

Python 以速度慢著稱,例如在 Python 中,正常循環比 C 中的類似循環慢幾個數量級。

Python 官方正在着手改進這一缺陷。2020 年秋,Mark Shannon 提出了關于 Python 的幾個性能改進。這個提議被稱為香農計劃 (Shannon Plan),他們希望通過幾個版本的更新将 Python 的速度提高 5 倍。不久之後微軟正式加入該計劃,該公司正在支援包括 Mark Shannon、Guido van Rossum 在内的開發人員,緻力于「Faster CPython」項目的研究。

「Faster CPython」項目中的一個重要提案是 PEP 659,在此基礎上,Python 3.11 有了許多改進。

PEP 659 描述了一種「specializing adaptive interpreter」。主要思想是通過優化經常執行的操作來加快代碼運作速度, 這類似于 JIT(just-in-time)編譯。隻是它不影響編譯,相反,Python 的位元組碼是動态調整或可更改的。

快10-60%!Python3.11來了!

研究人員在位元組碼生成中添加了一個名為「quickening」的新步驟,進而可以在運作時優化指令,并将它們替換為 adaptive 指令。

一旦函數被調用了一定次數,quickening 指令就會啟動。在 CPython 3.11 中,八次調用之後就會啟動 quickening。你可以通過調用 dis() 并設定 adaptive 參數來觀察解釋器如何适應位元組碼。

在基準測試中,CPython 3.11 比 CPython 3.10 平均快 25%。Faster CPython 項目是一個正在進行的項目,已經有幾個優化計劃在 2023 年 10 月與 Python 3.12 一起釋出。你可以在 GitHub 上關注該項目。

項目位址:https://github.com/faster-cpython/ideas

更好的異步任務文法

Python 中對異步程式設計的支援已經發展了很長時間。Python 2 時代添加了生成器,asyncio 庫最初是在 Python 3.4 中添加的,而 async 和 await 關鍵字是在 Python 3.5 中添加的。在 Python 3.11 中,你可以使用任務組(task groups),它為運作和監視異步任務提供了更簡潔的文法。

改進的類型變量

Python 是一種動态類型語言,但它通過可選的類型提示支援靜态類型。Python 靜态類型系統的基礎在 2015 年的 PEP 484 中定義。自 Python 3.5 以來,每個 Python 版本都引入了幾個與類型相關的新提案。

Python 3.11 釋出了 5 個與類型相關的 PEP,創下新高:

  • PEP 646: 可變泛型
  • PEP 655: 根據需要或可能丢失的情況标記單個 TypedDict 項
  • PEP 673: Self 類型
  • PEP 675: 任意文字字元串類型
  • PEP 681: 資料類轉換

支援 TOML 配置解析

TOML 是 Tom's Obvious Minimal Language 的縮寫。這是一種在過去十年中流行起來的配置檔案格式。在為包和項目指定中繼資料時,Python 社群已将 TOML 作為首選格式。

雖然 TOML 已被使用多年,但 Python 并沒有内置的 TOML 支援。當 tomllib 添加到标準庫時,Python 3.11 中的情況發生了變化。這個新子產品建立在 toml 第三方庫之上,允許解析 TOML 檔案。

以下是名為 units.toml 的 TOML 檔案示例:

快10-60%!Python3.11來了!

其他功能

除了以上主要更新和改進之外,Python 3.11 還有更多值得探索的功能,比如更快的程式啟動速度、對異常的更多改變以及對字元串格式的小幅改進。

更快的程式啟動速度

Faster CPython 項目的一大成果是實作了更快的啟動時間。當你運作 Python 腳本時,解釋器初始化需要一些操作。這就導緻即便是最簡單的程式也需要幾毫秒才能運作。

快10-60%!Python3.11來了!

在很多情況下,與運作代碼所需時間相比,啟動程式需要的時間可以忽略不計。但是在運作時間較短的腳本中,如典型的指令行應用程式,啟動時間可能會顯著影響程式性能。比如考慮如下腳本,它受到了經典 cowsay 程式的啟發。

快10-60%!Python3.11來了!

在 snakesay.py 中,你從指令行讀取一條消息,然後将這條消息列印在帶有一條可愛蛇的對話氣泡中。你可以讓蛇說任何話。這是指令行應用程式的基本示例,它運作得很快,但仍需要幾毫秒。這一開銷的很大部分發生在 Python 導入子產品時。

快10-60%!Python3.11來了!

你可以使用 - X importtime 選項來顯示導入子產品所用的時間。表中的數字為微秒為機關,最後一列是子產品名稱的格式。

快10-60%!Python3.11來了!

該示例分别運作在 Python 3.11 和 3.10 上,結果如下圖所示,Python 3.11 的導入速度更快,有助于 Python 程式更快地啟動。

快10-60%!Python3.11來了!

零成本異常

異常的内部表示在 Python 3.11 中有所不同。異常對象更輕量級,并且異常處理發生了變化。是以隻要不觸發 except 字句,try … except 塊中的開銷就越小。

所謂的零成本異常受到了 C++ 和 Java 等其他語言的啟發。當你的源代碼被編譯為位元組碼時,編譯器建立跳轉表,由此來實作零成本異常。如果引發異常,查詢這些跳轉表。如果沒有異常,則 try 塊中的代碼沒有運作時開銷。

異常組

此前,你了解到了任務組以及它們如何同時處理多個錯誤。這都要歸功于一個被稱為異常組的新功能。

我們可以這樣考慮異常組,它們是包裝了其他幾種正常異常的正常異常。雖然異常組在很多方面表現得像正常異常,但它們也支援特殊文法,幫助你有效地處理每個包裝異常。如下所示,你可以通過給出一個描述并列出包裝的異常來建立一個異常組。

快10-60%!Python3.11來了!

異常 Notes

正常異常具有添加任意 notes 的擴充能力。你可以使用. add_note() 向任何異常添加一個 note,并通過檢查.__notes__屬性來檢視現有 notes。

快10-60%!Python3.11來了!

負零格式化

使用浮點數進行計算時可能會遇到一個奇怪概念——負零。你可以觀察到負零和 regular zero 在 REPL 中呈現不同,如下所示。

快10-60%!Python3.11來了!