Python 3.15: 探索隱藏的新特性

雖然像 Python 3.15 這樣的大版本更新通常會以 lazy imports 和 Tachyon profiler 等備受矚目的特性主導話題,但語言更新的真正效用往往在於那些較小、漸進式的改進。這些「隱藏」的特性經常能解決開發者體驗中長期存在的摩擦點,提供更簡潔的語法和更安全的並行模式。

使用優雅的 TaskGroup 取消機制來增強 Asyncio

Python 中的結構化並行(Structured concurrency)主要透過 asyncio.TaskGroup 來處理,讓開發者能夠將多個並行任務視為單一單元進行管理。然而,過去要中斷這些群組一直相當繁瑣。以前,觸發優雅退出的唯一方法是在群組內拋出一個自定義異常,然後由 ExceptionGroup 捕捉並使用 contextlib.suppress 進行過濾。

Python 3.15 引入了 TaskGroup.cancel(),這顯著地簡化了這個過程。開發者不再需要依賴基於異常的流程控制來關閉任務群組,現在可以直接在群組實例上呼叫 .cancel()。這使得在滿足特定信號或條件時,能夠實現乾淨且無異常的退出,減少了背景任務管理所需的樣板代碼。

作為強大裝飾器的上下文管理器

許多開發者會將上下文管理器(context managers)作為裝飾器使用——這是自 Python 3.3 以來就有的功能。然而,這種模式有一個重大缺陷:當應用於 async functions、生成器(generators)或 async iterators 時會失效。因為這些函數在被呼叫時會立即返回一個生成器或協程對象,上下文管理器會在實際工作負載開始之前就結束。

在 Python 3.15 中,ContextDecorator 已更新,會檢查其包裝的函數類型。它現在能確保裝飾器涵蓋了被包裝對象的整個生命週期,無論它是標準函數、async function 還是生成器。這項改變有效地使上下文管理器成為實現裝飾器最可靠的方式之一,因為它消除了與包裝複雜函數類型相關的常見「誤用陷阱」(footguns)。

開發者筆記: 一些社群成員提出疑慮,認為這項改變缺乏明確的選擇加入(opt-in)機制,可能會改變依賴於先前(儘管已失效)行為的現有代碼庫的行為。

線程安全迭代器與自由線程(Free-threading)

迭代器對於 Python 的數據處理至關重要,但它們預設並非線程安全。在多線程環境中——特別是在 Python 朝向自由線程(free-threading)邁進的背景下——這可能導致跳過數值或內部狀態損壞。

為了應對此問題,Python 3.15 在 threading 模組中引入了幾個新工具:

  • threading.serialize_iterator:將現有的迭代器包裝起來使其變得線程安全。
  • threading.synchronized_iterator:一個裝飾器,將序列化應用於生成器函數的結果。
  • threading.concurrent_teeitertools.tee 的線程安全版本,它能將數值複製到多個迭代器中,供不同的線程使用。

以前,開發者高度依賴 queue.Queue 來同步線程間的數據消耗。這些新的原語(primitives)讓開發者能夠維持其基於迭代器的抽象,而無需為了配合基於隊列的架構而重寫邏輯。

額外福利:專用工具與數據類型

Counter XOR 操作

collections.Counter 長期以來一直支持集合類操作,例如交集 (&) และ union (|)。Python 3.15 增加了對稱差集運算符 (^),即 XOR。這讓開發者能夠找到存在於兩個 Counter 中但不同時存在於兩者的元素。

透過 frozendict 實現不可變 JSON 對象

隨著 frozendict (PEP 814) 的引入,Python 3.15 現在提供了一種方式來表示所有 JSON 類型——數組、布林值、浮點數、null、字符串和對象——以不可變且可雜湊(hashable)的形式。

為了實現這一點,json.loadjson.loads 現在包含了一個 array_hook 參數。結合現有的 object_hook,開發者可以直接將 JSON 解析為不可變結構:

import json
from frozendict import frozendict

# 直接將 JSON 解析為不可變的 tuple 和 frozendicts
json.loads('{"a": [1, 2, 3, 4]}', array_hook=tuple, object_hook=frozendict) 
# Result: frozendict({'a': (1, 2, 3, 4)})

這些新增功能共同標誌著向更強大的並行處理和更靈活的數據處理轉向,確保 Python 繼續在高性能、多線程應用中保持競爭力。

Sources