2020 年 1 月 1 日,Python 官方結(jié)束了對 Python 2 的維護,這意味著 Python 2 已完全退休,進入了 Python 3 時代。打從進入 3 版本以來,Python 官方已經(jīng)發(fā)布了眾多修改分支,現(xiàn)在來到了最新的版本 Python 3.11。其實研究界有個不公開的秘密,那就是 Python 運行速度并不快但容易上手,因此使用人數(shù)超級多,在眾多最受歡迎語言榜單中 Python 多次位列第一。很多開發(fā)者都期待這門語言的性能有所提升,還有人暢想 Python 4 會不會在某個不經(jīng)意的時刻到來,有這種想法的人可以放一放了,Python 之父 Van Rossum 都說了,Python 4.0 可能不會來了。Van Rossum 曾表示:「我和 Python 核心開發(fā)團隊的成員對 Python 4.0 沒什么想法,提不起興趣,估計至少會一直編號到 3.33。Python 的加速是漸進式的,3.11 版本會有新的速度提升,預(yù)計會比 3.10 快得多。」正如 Van Rossum 所說,根據(jù)官方資料顯示最新發(fā)布的 Python 3.11 比 Python 3.10 快 10-60%,對用戶更友好。這一版本歷經(jīng) 17 個月的開發(fā),現(xiàn)在公開可用。Python 3.11 的具體改進主要表現(xiàn)在:更詳實的 Error Tracebacks、更快的代碼執(zhí)行、更好的異步任務(wù)語法、改進類型變量、支持 TOML 配置解析以及一些其他非??岬墓δ埽ò焖賳印ero-Cost 異常處理、異常組等)。
Python 指導(dǎo)委員會成員和核心開發(fā)者、Python3.10/3.11 發(fā)布管理者 Pablo Galindo Salgado 表示,為了使 3.11 成為最好的 Python 版本,我們付出了很多努力。
Python 這門編程語言對初學(xué)者非常友好,它具有易于理解的語法和強大的數(shù)據(jù)結(jié)構(gòu)。但對于剛剛接觸 Python 的人來說卻存在一個難題,即如何解釋當(dāng) Python 遇到錯誤時顯示的 traceback。Python 3.11 將 Decorative annotation 添加到 tracebacks 中,以幫助用戶更快地解釋錯誤消息。想要獲得這種功能,可以將以下代碼添加到 inverse.py 文件中。
舉例來說,你可以使用 inverse() 來計算一個數(shù)的倒數(shù)。因為 0 沒有倒數(shù),所以在運行下列代碼時會拋出一個錯誤。
注意嵌入在 traceback 中的 ^ 和~ 符號,它們指向?qū)е洛e誤的代碼。與此前的 tracebacks 一樣,你應(yīng)該從底層開始,然后逐步向上。這種操作對發(fā)現(xiàn)錯誤非常有用,但如果代碼過于復(fù)雜,帶注釋的 tracebacks 會更好。Python 以速度慢著稱,例如在 Python 中,常規(guī)循環(huán)比 C 中的類似循環(huán)慢幾個數(shù)量級。Python 官方正在著手改進這一缺陷。2020 年秋,Mark Shannon 提出了關(guān)于 Python 的幾個性能改進。這個提議被稱為香農(nóng)計劃 (Shannon Plan),他們希望通過幾個版本的更新將 Python 的速度提高 5 倍。不久之后微軟正式加入該計劃,該公司正在支持包括 Mark Shannon、Guido van Rossum 在內(nèi)的開發(fā)人員,致力于「Faster CPython」項目的研究。「Faster CPython」項目中的一個重要提案是 PEP 659,在此基礎(chǔ)上,Python 3.11 有了許多改進。PEP 659 描述了一種「specializing adaptive interpreter」。主要思想是通過優(yōu)化經(jīng)常執(zhí)行的操作來加快代碼運行速度, 這類似于 JIT(just-in-time)編譯。只是它不影響編譯,相反,Python 的字節(jié)碼是動態(tài)調(diào)整或可更改的。
研究人員在字節(jié)碼生成中添加了一個名為「quickening」的新步驟,從而可以在運行時優(yōu)化指令,并將它們替換為 adaptive 指令。一旦函數(shù)被調(diào)用了一定次數(shù),quickening 指令就會啟動。在 CPython 3.11 中,八次調(diào)用之后就會啟動 quickening。你可以通過調(diào)用 dis() 并設(shè)置 adaptive 參數(shù)來觀察解釋器如何適應(yīng)字節(jié)碼。在基準測試中,CPython 3.11 比 CPython 3.10 平均快 25%。Faster CPython 項目是一個正在進行的項目,已經(jīng)有幾個優(yōu)化計劃在 2023 年 10 月與 Python 3.12 一起發(fā)布。你可以在 GitHub 上關(guān)注該項目。Python 3.12 目標:還可以更快!項目地址:https://github.com/faster-cpython/ideasPython 中對異步編程的支持已經(jīng)發(fā)展了很長時間。Python 2 時代添加了生成器,asyncio 庫最初是在 Python 3.4 中添加的,而 async 和 await 關(guān)鍵字是在 Python 3.5 中添加的。在 Python 3.11 中,你可以使用任務(wù)組(task groups),它為運行和監(jiān)視異步任務(wù)提供了更簡潔的語法。Python 是一種動態(tài)類型語言,但它通過可選的類型提示支持靜態(tài)類型。Python 靜態(tài)類型系統(tǒng)的基礎(chǔ)在 2015 年的 PEP 484 中定義。自 Python 3.5 以來,每個 Python 版本都引入了幾個與類型相關(guān)的新提案。Python 3.11 發(fā)布了 5 個與類型相關(guān)的 PEP,創(chuàng)下新高:- PEP 655: 根據(jù)需要或可能丟失的情況標記單個 TypedDict 項
- PEP 681: 數(shù)據(jù)類轉(zhuǎn)換
TOML 是 Tom's Obvious Minimal Language 的縮寫。這是一種在過去十年中流行起來的配置文件格式。在為包和項目指定元數(shù)據(jù)時,Python 社區(qū)已將 TOML 作為首選格式。雖然 TOML 已被使用多年,但 Python 并沒有內(nèi)置的 TOML 支持。當(dāng) tomllib 添加到標準庫時,Python 3.11 中的情況發(fā)生了變化。這個新模塊建立在 toml 第三方庫之上,允許解析 TOML 文件。以下是名為 units.toml 的 TOML 文件示例:
除了以上主要更新和改進之外,Python 3.11 還有更多值得探索的功能,比如更快的程序啟動速度、對異常的更多改變以及對字符串格式的小幅改進。Faster CPython 項目的一大成果是實現(xiàn)了更快的啟動時間。當(dāng)你運行 Python 腳本時,解釋器初始化需要一些操作。這就導(dǎo)致即便是最簡單的程序也需要幾毫秒才能運行。
在很多情況下,與運行代碼所需時間相比,啟動程序需要的時間可以忽略不計。但是在運行時間較短的腳本中,如典型的命令行應(yīng)用程序,啟動時間可能會顯著影響程序性能。比如考慮如下腳本,它受到了經(jīng)典 cowsay 程序的啟發(fā)。
在 snakesay.py 中,你從命令行讀取一條消息,然后將這條消息打印在帶有一條可愛蛇的對話氣泡中。你可以讓蛇說任何話。這是命令行應(yīng)用程序的基本示例,它運行得很快,但仍需要幾毫秒。這一開銷的很大部分發(fā)生在 Python 導(dǎo)入模塊時。
你可以使用 - X importtime 選項來顯示導(dǎo)入模塊所用的時間。表中的數(shù)字為微秒為單位,最后一列是模塊名稱的格式。
該示例分別運行在 Python 3.11 和 3.10 上,結(jié)果如下圖所示,Python 3.11 的導(dǎo)入速度更快,有助于 Python 程序更快地啟動。
異常的內(nèi)部表示在 Python 3.11 中有所不同。異常對象更輕量級,并且異常處理發(fā)生了變化。因此只要不觸發(fā) except 字句,try … except 塊中的開銷就越小。所謂的零成本異常受到了 C++ 和 Java 等其他語言的啟發(fā)。當(dāng)你的源代碼被編譯為字節(jié)碼時,編譯器創(chuàng)建跳轉(zhuǎn)表,由此來實現(xiàn)零成本異常。如果引發(fā)異常,查詢這些跳轉(zhuǎn)表。如果沒有異常,則 try 塊中的代碼沒有運行時開銷。此前,你了解到了任務(wù)組以及它們?nèi)绾瓮瑫r處理多個錯誤。這都要歸功于一個被稱為異常組的新功能。我們可以這樣考慮異常組,它們是包裝了其他幾種常規(guī)異常的常規(guī)異常。雖然異常組在很多方面表現(xiàn)得像常規(guī)異常,但它們也支持特殊語法,幫助你有效地處理每個包裝異常。如下所示,你可以通過給出一個描述并列出包裝的異常來創(chuàng)建一個異常組。
常規(guī)異常具有添加任意 notes 的擴展能力。你可以使用. add_note() 向任何異常添加一個 note,并通過檢查.__notes__屬性來查看現(xiàn)有 notes。
使用浮點數(shù)進行計算時可能會遇到一個奇怪概念——負零。你可以觀察到負零和 regular zero 在 REPL 中呈現(xiàn)不同,如下所示。
更多關(guān)于 Python 3.11 的更新細節(jié)請參閱原文檔。
原文:https://realpython.com/python311-new-features- END -