Python 3.10 有什么新變化?

發(fā)布版本

3.12.0a0

日期

五月 26, 2022

編者

Pablo Galindo Salgado

本文介紹了 Python 3.10 相比 3.9 的新增特性。

詳情請參閱 更新日志。

摘要 -- 發(fā)布重點(diǎn)?

新的語(yǔ)法特性:

  • PEP 634, 結構化模式匹配: 規范說(shuō)明

  • PEP 635, 結構化模式匹配: 動(dòng)機與理由

  • PEP 636, 結構化模式匹配: 教程

  • bpo-12782,加圓括號的上下文管理器現在正式被允許使用。

標準庫中的新特性:

  • PEP 618,向 zip 添加可選的長(cháng)度檢查。

解釋器的改進(jìn):

  • PEP 626,在調試和其他工具中使用精確的行號。

新的類(lèi)型標注特性:

  • PEP 604,允許 X | Y 形式的聯(lián)合類(lèi)型寫(xiě)法

  • PEP 613,顯式類(lèi)型別名

  • PEP 612,形參規格變量

重要的棄用、移除或限制:

  • PEP 644,要求 OpenSSL 1.1.1 或更新的版本

  • PEP 632,棄用 distutils 模塊。

  • PEP 623,棄用并準備移除 PyUnicodeObject 中的 wstr 成員。

  • PEP 624,移除 Py_UNICODE 編碼器 API

  • PEP 597,增加可選的 EncodingWarning

新的特性?

帶圓括號的上下文管理器?

現在已支持使用外層圓括號來(lái)使多個(gè)上下文管理器可以連續多行地書(shū)寫(xiě)。 這允許將過(guò)長(cháng)的上下文管理器集能夠以與之前 import 語(yǔ)句類(lèi)似的方式格式化為多行的形式。 例如,以下這些示例寫(xiě)法現在都是有效的:

with (CtxManager() as example):
    ...

with (
    CtxManager1(),
    CtxManager2()
):
    ...

with (CtxManager1() as example,
      CtxManager2()):
    ...

with (CtxManager1(),
      CtxManager2() as example):
    ...

with (
    CtxManager1() as example1,
    CtxManager2() as example2
):
    ...

在被包含的分組末尾過(guò)可以使用一個(gè)逗號作為結束:

with (
    CtxManager1() as example1,
    CtxManager2() as example2,
    CtxManager3() as example3,
):
    ...

這個(gè)新語(yǔ)法使用了新解析器的非 LL(1) 功能。 請查看 PEP 617 來(lái)了解更多細節。

(由 Guido van Rossum, Pablo Galindo 和 Lysandros Nikolaou 在 bpo-12782bpo-40334 中貢獻。)

更清楚的錯誤消息?

SyntaxError?

現在當解析包含有未關(guān)閉括號的代碼時(shí)解釋器會(huì )包括未關(guān)閉括號的位置而不是顯示 SyntaxError: unexpected EOF while parsing 并指向某個(gè)不正確的位置。 例如,考慮以下代碼(注意未關(guān)閉的 “ { ”):

expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
            38: 4, 39: 4, 45: 5, 46: 5, 47: 5, 48: 5, 49: 5, 54: 6,
some_other_code = foo()

之前版本的解釋器會(huì )報告令人迷惑的語(yǔ)法錯誤位置:

File "example.py", line 3
    some_other_code = foo()
                    ^
SyntaxError: invalid syntax

但在 Python 3.10 中則會(huì )發(fā)出信息量更多的錯誤提示:

File "example.py", line 1
    expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
               ^
SyntaxError: '{' was never closed

類(lèi)似地,涉及未關(guān)閉字符串字面值 (單重引號和三重引號) 的錯誤現在會(huì )指向字符串的開(kāi)頭而不是報告 EOF/EOL。

這些改進(jìn)的靈感來(lái)自 PyPy 解釋器之前所進(jìn)行的工作。

(由 Pablo Galindo 在 bpo-42864 以及 Batuhan Taskaya 在 bpo-40176 中貢獻。)

解釋器所引發(fā)的 SyntaxError 異?,F在將高亮構成語(yǔ)法錯誤本身的完整異常錯誤內容,而不是僅提示檢測到問(wèn)題的位置。 這樣,不再(同 Python 3.10 之前那樣)僅顯示:

>>>
>>> foo(x, z for z in range(10), t, w)
  File "<stdin>", line 1
    foo(x, z for z in range(10), t, w)
           ^
SyntaxError: Generator expression must be parenthesized

現在 Python 3.10 將這樣顯示異常:

>>>
>>> foo(x, z for z in range(10), t, w)
  File "<stdin>", line 1
    foo(x, z for z in range(10), t, w)
           ^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized

這個(gè)改進(jìn)是由 Pablo Galindo 在 bpo-43914 中貢獻的。

大量新增的專(zhuān)門(mén)化 SyntaxError 異常消息已被添加。 其中最主要的一些如下所示:

  • 在代碼塊之前缺失 :

    >>>
    >>> if rocket.position > event_horizon
      File "<stdin>", line 1
        if rocket.position > event_horizon
                                          ^
    SyntaxError: expected ':'
    

    (由 Pablo Galindo 在 bpo-42997 中貢獻。)

  • 在推導式的目標中有不帶圓括號的元組:

    >>>
    >>> {x,y for x,y in zip('abcd', '1234')}
      File "<stdin>", line 1
        {x,y for x,y in zip('abcd', '1234')}
         ^
    SyntaxError: did you forget parentheses around the comprehension target?
    

    (由 Pablo Galindo 在 bpo-43017 中貢獻。)

  • 在多項集字面值中和表達式之間缺失逗號:

    >>>
    >>> items = {
    ... x: 1,
    ... y: 2
    ... z: 3,
      File "<stdin>", line 3
        y: 2
           ^
    SyntaxError: invalid syntax. Perhaps you forgot a comma?
    

    (由 Pablo Galindo 在 bpo-43822 中貢獻。)

  • 多個(gè)異常類(lèi)型不帶圓括號:

    >>>
    >>> try:
    ...     build_dyson_sphere()
    ... except NotEnoughScienceError, NotEnoughResourcesError:
      File "<stdin>", line 3
        except NotEnoughScienceError, NotEnoughResourcesError:
               ^
    SyntaxError: multiple exception types must be parenthesized
    

    (由 Pablo Galindo 在 bpo-43149 中貢獻。)

  • 字典字面值中缺失 : 和值:

    >>>
    >>> values = {
    ... x: 1,
    ... y: 2,
    ... z:
    ... }
      File "<stdin>", line 4
        z:
         ^
    SyntaxError: expression expected after dictionary key and ':'
    
    >>> values = {x:1, y:2, z w:3}
      File "<stdin>", line 1
        values = {x:1, y:2, z w:3}
                            ^
    SyntaxError: ':' expected after dictionary key
    

    (由 Pablo Galindo 在 bpo-43823 中貢獻)

  • try 代碼塊不帶 exceptfinally 代碼塊:

    >>>
    >>> try:
    ...     x = 2
    ... something = 3
      File "<stdin>", line 3
        something  = 3
        ^^^^^^^^^
    SyntaxError: expected 'except' or 'finally' block
    

    (由 Pablo Galindo 在 bpo-44305 中貢獻。)

  • 在比較中使用 = 而不是 ==

    >>>
    >>> if rocket.position = event_horizon:
      File "<stdin>", line 1
        if rocket.position = event_horizon:
                           ^
    SyntaxError: cannot assign to attribute here. Maybe you meant '==' instead of '='?
    

    (由 Pablo Galindo 在 bpo-43797 中貢獻。)

  • 在 f-字符串中使用 *

    >>>
    >>> f"Black holes {*all_black_holes} and revelations"
      File "<stdin>", line 1
        (*all_black_holes)
         ^
    SyntaxError: f-string: cannot use starred expression here
    

    (由 Pablo Galindo 在 bpo-41064 中貢獻。)

IndentationError?

許多 IndentationError 異?,F在具有更多上下文來(lái)提示是何種代碼塊需要縮進(jìn),包括語(yǔ)句的位置:

>>>
>>> def foo():
...    if lel:
...    x = 2
  File "<stdin>", line 3
    x = 2
    ^
IndentationError: expected an indented block after 'if' statement in line 2

AttributeError?

當打印 AttributeError 時(shí),PyErr_Display() 將提供引發(fā)異常的對象中類(lèi)似屬性名稱(chēng)的建議:

>>>
>>> collections.namedtoplo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'collections' has no attribute 'namedtoplo'. Did you mean: namedtuple?

(由 Pablo Galindo 在 bpo-38530 中貢獻。)

警告

請注意如果未調用 PyErr_Display() 來(lái)顯示錯誤則此特性將沒(méi)有效果,這可能發(fā)生在使用了某些其他自定義錯誤顯示函數的時(shí)候。 這在某些 REPL 例如 IPython 上是一種常見(jiàn)的情況。

NameError?

當打印解釋器所引發(fā)的 NameError 時(shí),PyErr_Display() 將提供引發(fā)異常的函數中類(lèi)似變量名稱(chēng)的建議:

>>>
>>> schwarzschild_black_hole = None
>>> schwarschild_black_hole
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'schwarschild_black_hole' is not defined. Did you mean: schwarzschild_black_hole?

(由 Pablo Galindo 在 bpo-38530 中貢獻。)

警告

請注意如果未調用 PyErr_Display() 來(lái)顯示錯誤則此特性將沒(méi)有效果,這可能發(fā)生在使用了某些其他自定義錯誤顯示函數的時(shí)候。 這在某些 REPL 例如 IPython 中是一種常見(jiàn)的情況。

PEP 626:在調試和其他工具中使用精確的行號?

PEP 626 帶來(lái)了更精確可靠的行號用于調試、性能分析和測試工具。 所有被執行的代碼行都會(huì )并且只有被執行的代碼行才會(huì )生成帶有正確行號的追蹤事件。

幀對象的 f_lineno 屬性將總是包含預期的行號。

代碼對象的 co_lnotab 屬性已被棄用并將在 3.12 中被移除。 需要從偏移量轉換為行號的代碼應改用新的 co_lines() 方法。

PEP 634:結構化模式匹配?

增加了采用模式加上相應動(dòng)作的 match 語(yǔ)句case 語(yǔ)句 的形式的結構化模式匹配。 模式由序列、映射、基本數據類(lèi)型以及類(lèi)實(shí)例構成。 模式匹配使得程序能夠從復雜的數據類(lèi)型中提取信息、根據數據結構實(shí)現分支,并基于不同的數據形式應用特定的動(dòng)作。

語(yǔ)法與操作?

模式匹配的通用語(yǔ)法如下:

match subject:
    case <pattern_1>:
        <action_1>
    case <pattern_2>:
        <action_2>
    case <pattern_3>:
        <action_3>
    case _:
        <action_wildcard>

match 語(yǔ)句接受一個(gè)表達式并將其值與以一個(gè)或多個(gè) case 語(yǔ)句塊形式給出的一系列模式進(jìn)行比較。 具體來(lái)說(shuō),模式匹配的操作如下:

  1. 使用具有特定類(lèi)型和形狀的數據 (subject)

  2. 針對 subjectmatch 語(yǔ)句中求值

  3. 從上到下對 subject 與 case 語(yǔ)句中的每個(gè)模式進(jìn)行比較直到確認匹配到一個(gè)模式。

  4. 執行與被確認匹配的模式相關(guān)聯(lián)的動(dòng)作。

  5. 如果沒(méi)有確認到一個(gè)完全的匹配,則如果提供了使用通配符 _ 的最后一個(gè) case 語(yǔ)句,則它將被用作已匹配模式。 如果沒(méi)有確認到一個(gè)完全的匹配并且不存在使用通配符的 case 語(yǔ)句,則整個(gè) match 代碼塊不執行任何操作。

聲明性方式?

讀者可能是通過(guò) C, Java 或 JavaScript (以及其他許多語(yǔ)言) 中的 switch 語(yǔ)句將一個(gè)目標 (數據對象) 與一個(gè)字面值 (模式) 進(jìn)行匹配的簡(jiǎn)單例子了解到模式匹配的概念的。 switch 語(yǔ)句常常被用來(lái)將一個(gè)對象/表達式與包含在 case 語(yǔ)句中的字面值進(jìn)行比較。

更強大的模式匹配例子可以在 Scala 和 Elixir 等語(yǔ)言中找到。 這種結構化模式匹配方式是“聲明性”的并且會(huì )顯式地為所要匹配的數據指定條件(模式)。

雖然使用嵌套的“if”語(yǔ)句的“命令性”系列指令可以被用來(lái)完成類(lèi)似結構化模式匹配的效果,但它沒(méi)有“聲明性”方式那樣清晰。 相反地,“聲明性”方式指定了一個(gè)匹配所要滿(mǎn)足的條件,并且通過(guò)其顯式的模式使之更為易讀。 雖然結構化模式匹配可以采取將一個(gè)變量與一個(gè) case 語(yǔ)句中的字面值進(jìn)行比較的最簡(jiǎn)單形式來(lái)使用,但它對于 Python 的真正價(jià)值在于其針對目標類(lèi)型和形狀的處理操作。

簡(jiǎn)單模式:匹配一個(gè)字面值?

讓我們把這個(gè)例子看作是模式匹配的最簡(jiǎn)單形式:一個(gè)值,即主詞,被匹配到幾個(gè)字面值,即模式。在下面的例子中,status 是匹配語(yǔ)句的主詞。模式是每個(gè) case 語(yǔ)句,字面值代表請求狀態(tài)代碼。匹配后,將執行與該 case 相關(guān)的動(dòng)作:

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"
        case _:
            return "Something's wrong with the internet"

如果傳給上述函數的 status 為 418,則會(huì )返回 "I'm a teapot"。 如果傳給上述函數的 status 為 500,則帶有 _ 的 case 語(yǔ)句將作為通配符匹配,并會(huì )返回 "Something's wrong with the internet"。 請注意最后一個(gè)代碼塊:變量名 _ 將作為 通配符 并確保目標將總是被匹配。 _ 的使用是可選的。

你可以使用 | (“ or ”)在一個(gè)模式中組合幾個(gè)字面值:

case 401 | 403 | 404:
    return "Not allowed"
無(wú)通配符的行為?

如果我們修改上面的例子,去掉最后一個(gè) case 塊,這個(gè)例子就變成:

def http_error(status):
    match status:
        case 400:
            return "Bad request"
        case 404:
            return "Not found"
        case 418:
            return "I'm a teapot"

如果不在 case 語(yǔ)句中使用 _,可能會(huì )出現不存在匹配的情況。如果不存在匹配,則行為是一個(gè) no-op。例如,如果傳入了值為 500 的 status ,就會(huì )發(fā)生 no-op。

帶有字面值和變量的模式?

模式可以看起來(lái)像解包形式,而且模式可以用來(lái)綁定變量。在這個(gè)例子中,一個(gè)數據點(diǎn)可以被解包為它的 x 坐標和 y 坐標:

# point is an (x, y) tuple
match point:
    case (0, 0):
        print("Origin")
    case (0, y):
        print(f"Y={y}")
    case (x, 0):
        print(f"X={x}")
    case (x, y):
        print(f"X={x}, Y={y}")
    case _:
        raise ValueError("Not a point")

第一個(gè)模式有兩個(gè)字面值 (0, 0) ,可以看作是上面所示字面值模式的擴展。接下來(lái)的兩個(gè)模式結合了一個(gè)字面值和一個(gè)變量,而變量 綁定 了一個(gè)來(lái)自主詞的值(point)。 第四種模式捕獲了兩個(gè)值,這使得它在概念上類(lèi)似于解包賦值 (x, y) = point 。

模式和類(lèi)?

如果你使用類(lèi)來(lái)結構化你的數據,你可以使用類(lèi)的名字,后面跟一個(gè)類(lèi)似構造函數的參數列表,作為一種模式。這種模式可以將類(lèi)的屬性捕捉到變量中:

class Point:
    x: int
    y: int

def location(point):
    match point:
        case Point(x=0, y=0):
            print("Origin is the point's location.")
        case Point(x=0, y=y):
            print(f"Y={y} and the point is on the y-axis.")
        case Point(x=x, y=0):
            print(f"X={x} and the point is on the x-axis.")
        case Point():
            print("The point is located somewhere else on the plane.")
        case _:
            print("Not a point")
帶有位置參數的模式?

你可以在某些為其屬性提供了排序的內置類(lèi)(例如 dataclass)中使用位置參數。 你也可以通過(guò)在你的類(lèi)中設置 __match_args__ 特殊屬性來(lái)為模式中的屬性定義一個(gè)專(zhuān)門(mén)的位置。 如果它被設為 ("x", "y"),則以下模式均為等價(jià)的(并且都是將 y 屬性綁定到 var 變量):

Point(1, var)
Point(1, y=var)
Point(x=1, y=var)
Point(y=var, x=1)

嵌套模式?

模式可以任意地嵌套。 例如,如果我們的數據是由點(diǎn)組成的短列表,則它可以這樣被匹配:

match points:
    case []:
        print("No points in the list.")
    case [Point(0, 0)]:
        print("The origin is the only point in the list.")
    case [Point(x, y)]:
        print(f"A single point {x}, {y} is in the list.")
    case [Point(0, y1), Point(0, y2)]:
        print(f"Two points on the Y axis at {y1}, {y2} are in the list.")
    case _:
        print("Something else is found in the list.")

復雜模式和通配符?

到目前為止,這些例子僅在最后一個(gè) case 語(yǔ)句中使用了 _。 但通配符可以被用在更復雜的模式中,例如 ('error', code, _)。 舉例來(lái)說(shuō):

match test_variable:
    case ('warning', code, 40):
        print("A warning has been received.")
    case ('error', code, _):
        print(f"An error {code} occurred.")

在上述情況下,test_variable 將可匹配 ('error', code, 100) 和 ('error', code, 800)。

約束項?

我們可以向一個(gè)模式添加 if 子句,稱(chēng)為“約束項”。 如果約束項為假值,則 match 將繼續嘗試下一個(gè) case 語(yǔ)句塊。 請注意值的捕獲發(fā)生在約束項被求值之前。:

match point:
    case Point(x, y) if x == y:
        print(f"The point is located on the diagonal Y=X at {x}.")
    case Point(x, y):
        print(f"Point is not on the diagonal.")

其他關(guān)鍵特性?

一些其他關(guān)鍵特性:

  • 類(lèi)似于解包賦值,元組和列表模式具有完全相同的含義,而且實(shí)際上能匹配任意序列。 從技術(shù)上說(shuō),目標必須為一個(gè)序列。 因而,一個(gè)重要的例外是模式不能匹配迭代器。 而且,為了避免一個(gè)常見(jiàn)的錯誤,序列模式不能匹配字符串。

  • 序列模式支持通配符: [x, y, *rest](x, y, *rest) 的作用類(lèi)似于解包賦值中的通配符。 在 * 之后的名稱(chēng)也可以為 _,因此 (x, y, *_) 可以匹配包含兩個(gè)條目的序列而不必綁定其余的條目。

  • 映射模式: {"bandwidth": b, "latency": l} 會(huì )從一個(gè)字典中捕獲 "bandwidth""latency" 值。 與序列模式不同,額外的鍵會(huì )被忽略。 也支持通配符 **rest。 (但 **_ 是冗余的,因而不被允許。)

  • 子模式可使用 as 關(guān)鍵字來(lái)捕獲:

    case (Point(x1, y1), Point(x2, y2) as p2): ...
    

    x1, y1, x2, y2 等綁定就如你在沒(méi)有 as 子句的情況下所期望的,而 p2 會(huì )綁定目標的整個(gè)第二項。

  • 大多數字面值是按相等性比較的。 但是,單例對象 True, FalseNone 則是按標識號比較的。

  • 命名常量也可以在模式中使用。 這些命名常量必須為帶點(diǎn)號的名稱(chēng)以防止常量被解讀為捕獲變量:

    from enum import Enum
    class Color(Enum):
        RED = 0
        GREEN = 1
        BLUE = 2
    
    match color:
        case Color.RED:
            print("I see red!")
        case Color.GREEN:
            print("Grass is green")
        case Color.BLUE:
            print("I'm feeling the blues :(")
    

完整規格說(shuō)明參見(jiàn) PEP 634。 動(dòng)機與理由參見(jiàn) PEP 635,更詳細的教程參見(jiàn) PEP 636。

可選的 EncodingWarningencoding="locale" 選項?

TextIOWrapperopen() 的默認編碼格式取決于具體的平臺和語(yǔ)言區域設置。 由于 UTF-8 被用于大多數 Unix 平臺,當打開(kāi) UTF-8 文件 (例如 JSON, YAML, TOML, Markdown) 時(shí)省略 encoding 選項是一個(gè)非常常見(jiàn)的錯誤。 例如:

# BUG: "rb" mode or encoding="utf-8" should be used.
with open("data.json") as f:
    data = json.load(f)

為了便于查找此類(lèi)錯誤,增加了可選的 EncodingWarning。 它會(huì )在 sys.flags.warn_default_encoding 為真值并使用了語(yǔ)言區域指定的默認編碼格式時(shí)被發(fā)出。

增加了 -X warn_default_encoding 選項和 PYTHONWARNDEFAULTENCODING 來(lái)啟用相應警告。

請參閱 文本編碼格式 了解更多信息。

其他語(yǔ)言特性修改?

  • int 類(lèi)型新增了一個(gè)方法 int.bit_count(),返回給定整數的二進(jìn)制展開(kāi)中值為一的位數,或稱(chēng)“比特計量”。 (由 Niklas Fiekas 在 bpo-29882 中貢獻。)

  • 現在 dict.keys(), dict.values()dict.items() 所返回的視圖都有一個(gè) mapping 屬性,它給出包裝了原始字典的 types.MappingProxyType 對象。 (由 Dennis Sweeney 在 bpo-40890 中貢獻。)

  • PEP 618: 現在 zip() 函數有一個(gè)可選的 strict 旗標,用于要求所有可迭代對象的長(cháng)度都相等。

  • 接受整數參數的內置和擴展函數不再接受 Decimal, Fraction 以及其他可被轉換為整數但會(huì )丟失精度(即具有 __int__() 方法但沒(méi)有 __index__() 方法)的對象。 (由 Serhiy Storchaka 在 bpo-37999 中貢獻。)

  • 如果 object.__ipow__() 返回 NotImplemented,該運算符將正確地按照預期回退至 object.__pow__()object.__rpow__()。 (由 Alex Shkop 在 bpo-38302 中貢獻。)

  • 現在賦值表達式可以不帶圓括號地在集合字面值和集合推導式中使用,也可以在序列索引號中使用(但不能用于切片)。

  • 函數具有一個(gè)新的 __builtins__ 屬性,當函數被執行時(shí)它會(huì )被用于查找內置符號,而不是在 __globals__['__builtins__'] 中查找。 如果 __globals__["__builtins__"] 存在則該屬性將基于它來(lái)初始化,否則將基于當前的內置函數。 (由 Mark Shannon 在 bpo-42990 中貢獻。)

  • 增加了兩個(gè)新的內置函數 —— aiter()anext() 以分別提供與 iter()next() 對應的異步版本。 (由 Joshua Bronson, Daniel Pope 和 Justin Wang 在 bpo-31861 中貢獻。)

  • 靜態(tài)方法 (@staticmethod) 和類(lèi)方法 (@classmethod) 現在會(huì )繼承方法屬性 (__module__, __name__, __qualname__, __doc__, __annotations__) 并具有一個(gè)新的 __wrapped__ 屬性。 此外,靜態(tài)方法現在還是與常規函數一樣的可調用對象。 (由 Victor Stinner 在 bpo-43682 中貢獻。)

  • 復雜目標的注解( PEP 526 定義的除 simple name 之外的一切復雜目標)在運行時(shí)不再受 from __future__ import annotations 的影響。(由Batuhan Taskaya 在 bpo-42737 中貢獻)。

  • 類(lèi)和模塊對象現在可以按需創(chuàng )建空的注解字典。為保證向下兼容,這些注解數據將存儲于對象的 __dict__ 中。這改進(jìn)了 __annotations__ 的最佳用法;更多信息請參閱 對象注解屬性的最佳實(shí)踐 。(由 Larry Hastings 在 bpo-43901 中貢獻)

  • 由于會(huì )產(chǎn)生副作用,現在 from __future__ import annotations 時(shí)禁止使用包含 yield 、 yield from 、 await 或已命名表達式的注解。(由 Batuhan Taskaya 在 bpo-42725 中貢獻)

  • 未綁定變量、super() 和其他可能改變符號表處理的表達式,現在在 from __future__ import annotations 時(shí)不能用作注解。(由 Batuhan Taskaya 在 bpo-42725 中貢獻)

  • float 類(lèi)型和 decimal.Decimal 類(lèi)型的 NaN 值的哈希值現在取決于對象身份。以前,即便 NaN 值彼此不等,也都是哈希為 0。在創(chuàng )建包含多個(gè) NaN 的字典和集合時(shí),由于哈希沖突過(guò)度,導致了運行代價(jià)可能會(huì )二次方增長(cháng)。(由 Raymond Hettinger 在 bpo-43475 中貢獻)

  • A SyntaxError (instead of a NameError) will be raised when deleting the __debug__ constant. (Contributed by Dong-hee Na in bpo-45000.)

  • SyntaxError exceptions now have end_lineno and end_offset attributes. They will be None if not determined. (Contributed by Pablo Galindo in bpo-43914.)

新增模塊?

  • 無(wú)。

改進(jìn)的模塊?

asyncio?

加入了缺失的 connect_accepted_socket() 方法。(由 Alex Gr?nholm 在 bpo-41332 中貢獻)

argparse?

在 argparse 的幫助中,將“可選參數”這一誤導性短語(yǔ)改為“可選項”。某些測試代碼如果依賴(lài)精確的輸出匹配,可能需要調整。(由 Raymond Hettinger 在 bpo-9694 中貢獻)

array?

現在, array.arrayindex() 方法擁有可選的 startstop 參數。(由 Anders Lorentsen 和 Zackery Spytz 在 bpo-31956 中貢獻)

asynchat、asyncore 和 smtpd?

從 Python 3.6 開(kāi)始,這些模塊在其文檔中已被標為廢棄?,F在這三個(gè)模塊都增加了一個(gè)導入時(shí)警告 DeprecationWarning。

base64?

增加 base64.b32hexencode()base64.b32hexdecode() 以支持帶有擴展十六進(jìn)制字母的 Base32 編碼。

bdb?

增加 clearBreakpoints() ,用于重置所有已設斷點(diǎn)。(由 Irit Katriel 在 bpo-24160 中貢獻)

bisect?

Added the possibility of providing a key function to the APIs in the bisect module. (Contributed by Raymond Hettinger in bpo-4356.)

編碼器?

增加一個(gè) codecs.unregister() 函數,用于取消對編解碼器搜索函數的注冊。(由 Hai Shi 在 bpo-41842 中貢獻)

collections.abc?

現在, parameterized genericcollections.abc.Callable__args__typing.Callable 一致了。 collections.abc.Callable generic 現在將類(lèi)型參數扁平化了,類(lèi)似于 typing.Callable 當前的做法。這意味著(zhù) collections.abc.Callable[[int, str], str] 將帶有 (int, str, str) 的參數 __args__;以前是 ([int, str], str) 。為了做到這一變化, types.GenericAlias 現在可以被子類(lèi)化,當對 collections.abc.Callable 類(lèi)型進(jìn)行下標訪(fǎng)問(wèn)時(shí),將返回一個(gè)子類(lèi)。注意,collections.abc.Callable 非法的參數化形式可能會(huì )觸發(fā) TypeError ,而在 Python 3.9 中可能就靜默了。(由 Ken Jin 在 bpo-42195 中貢獻)

contextlib?

增加了一個(gè)上下文管理器 contextlib.aclosing() ,以便能安全關(guān)閉異步生成器和代表異步釋放資源的對象。(由 Joongi Kim 和 John Belmonte 在 bpo-41229 中貢獻)

contextlib.nullcontext() 加入異步上下文管理器支持。由 Tom Gringauz 在 bpo-41543 中貢獻)

加入 AsyncContextDecorator,以便支持用異步上下文管理器作為裝飾器。

curses?

在 ncurses 6.1 中增加的擴展顏色函數將會(huì )由 curses.color_content() 、 curses.init_color() 、 curses.init_pair()curses.pair_content() 透明地使用。新增的函數 curses.has_extended_color_support() 將指明下層的 ncurses 庫是否提供了擴展顏色支持。(由 Jeffrey Kintscher 和 Hans Petter Jansson 在 bpo-36982 中貢獻)

現在常量 BUTTON5_* 如果是由底層的 curses 庫提供的,則會(huì )在 curses 模塊中體現。(由 Zackery Spytz 在 bpo-39273 中貢獻)

dataclasses?

__slots__?

Added slots parameter in dataclasses.dataclass() decorator. (Contributed by Yurii Karabas in bpo-42269)

Keyword-only fields?

dataclasses now supports fields that are keyword-only in the generated __init__ method. There are a number of ways of specifying keyword-only fields.

You can say that every field is keyword-only:

from dataclasses import dataclass

@dataclass(kw_only=True)
class Birthday:
    name: str
    birthday: datetime.date

Both name and birthday are keyword-only parameters to the generated __init__ method.

You can specify keyword-only on a per-field basis:

from dataclasses import dataclass, field

@dataclass
class Birthday:
    name: str
    birthday: datetime.date = field(kw_only=True)

Here only birthday is keyword-only. If you set kw_only on individual fields, be aware that there are rules about re-ordering fields due to keyword-only fields needing to follow non-keyword-only fields. See the full dataclasses documentation for details.

You can also specify that all fields following a KW_ONLY marker are keyword-only. This will probably be the most common usage:

from dataclasses import dataclass, KW_ONLY

@dataclass
class Point:
    x: float
    y: float
    _: KW_ONLY
    z: float = 0.0
    t: float = 0.0

Here, z and t are keyword-only parameters, while x and y are not. (Contributed by Eric V. Smith in bpo-43532)

distutils?

整個(gè) distutils 包已被廢棄,將在 Python 3.12 中移除。其用指定包構建程序的功能已被第三方軟件包 setuptoolspackaging 完全取代,而且大多數其他常用的 API 在標準庫的其他地方都可以調用(如 platform 、 shutil 、 subprocesssysconfig)。目前沒(méi)有遷移 distutils 其他功能的計劃,用到其他功能的應用程序應該準備好自己保留一份拷貝。請參考 PEP 632 。

在 Python 3.8 中廢棄的 bdist_wininst 命令已被移除?,F在在 Windows 中發(fā)布二進(jìn)制包推薦采用 bdist_wheel 命令。(由 Victor Stinner 在 bpo-42802 中貢獻)

doctest?

若模塊中沒(méi)有定義 __loader__ ,則回退至使用 __spec__.loader 。(由 Brett Cannon 在 bpo-42133 中貢獻)

encodings?

現在 encodings.normalize_encoding() 會(huì )忽略非 ASCII 字符。(由 Hai Shi 在 bpo-39337 中貢獻)

enum?

Enum __repr__() now returns enum_name.member_name and __str__() now returns member_name. Stdlib enums available as module constants have a repr() of module_name.member_name. (Contributed by Ethan Furman in bpo-40066.)

Add enum.StrEnum for enums where all members are strings. (Contributed by Ethan Furman in bpo-41816.)

fileinput?

fileinput.input()fileinput.FileInput 中增加了 encodingerrors 形參。 (由 Inada Naoki 在 bpo-43712 中貢獻。)

現在 fileinput.hook_compressed() 會(huì )在 mode 為 "r" 且文件被壓縮時(shí)返回 TextIOWrapper,與未壓縮文件一致。 (由 Inada Naoki 在 bpo-5758 中貢獻。)

faulthandler?

現在 faulthandler 模塊會(huì )檢測在垃圾回收期間是否發(fā)生嚴重錯誤。 (由 Victor Stinner 在 bpo-44466 中貢獻)

gc?

gc.get_objects(), gc.get_referrers()gc.get_referents() 添加了審計鉤子。 (由 Pablo Galindo 在 bpo-43439 中貢獻。)

glob?

glob()iglob() 中增加了 root_dirdir_fd 形參,用于指定搜索的根目錄。(由 Serhiy Storchaka 在 bpo-38144 中貢獻)

hashlib?

hashlib 模塊要求 OpenSSL 1.1.1 或更新版本。 (由 Christian Heimes 在 PEP 644bpo-43669 中貢獻。)

hashlib 模塊已初步支持 OpenSSL 3.0.0。 (由 Christian Heimes 在 bpo-38820 及其他問(wèn)題事項中貢獻。)

純 Python 的回退版 pbkdf2_hmac() 已被棄用。 未來(lái) PBKDF2-HMAC 將僅在 Python 帶有 OpenSSL 編譯時(shí)才可用。(由 Christian Heimes 在 bpo-43880 中貢獻)

hmac?

現在 hmac 模塊會(huì )在內部使用 OpenSSL 的 HMAC 實(shí)現。 (由 Christian Heimes 在 bpo-40645 中貢獻。)

IDLE 與 idlelib?

Make IDLE invoke sys.excepthook() (when started without '-n'). User hooks were previously ignored. (Contributed by Ken Hilton in bpo-43008.)

Rearrange the settings dialog. Split the General tab into Windows and Shell/Ed tabs. Move help sources, which extend the Help menu, to the Extensions tab. Make space for new options and shorten the dialog. The latter makes the dialog better fit small screens. (Contributed by Terry Jan Reedy in bpo-40468.) Move the indent space setting from the Font tab to the new Windows tab. (Contributed by Mark Roseman and Terry Jan Reedy in bpo-33962.)

The changes above were backported to a 3.9 maintenance release.

增加了 Shell 側欄。 將主提示符(“>>>”)移至側欄。二級提示符(“...”)也加入側欄。在編輯器的行號側欄上鼠標單擊和可選的拖動(dòng),會(huì )選定一行或多行文本。在選定文本行后右擊將顯示包含“copy with prompts”的上下文菜單。這會(huì )將側欄的提示符與選定文本行合并。該選項也會(huì )在文本的上下文菜單中顯示。(由 Tal Einat 在 bpo-37903 中貢獻)

Use spaces instead of tabs to indent interactive code. This makes interactive code entries 'look right'. Making this feasible was a major motivation for adding the shell sidebar. (Contributed by Terry Jan Reedy in bpo-37892.)

Highlight the new soft keywords match, case, and _ in pattern-matching statements. However, this highlighting is not perfect and will be incorrect in some rare cases, including some _-s in case patterns. (Contributed by Tal Einat in bpo-44010.)

New in 3.10 maintenance releases.

Apply syntax highlighting to .pyi files. (Contributed by Alex Waygood and Terry Jan Reedy in bpo-45447.)

importlib.metadata?

importlib_metadata 4.6(history)的功能一致。

importlib.metadata entry points now provide a nicer experience for selecting entry points by group and name through a new importlib.metadata.EntryPoints class. See the Compatibility Note in the docs for more info on the deprecation and usage.

添加了 importlib.metadata.packages_distributions(),用于將頂級 Python 模塊和包解析為其 importlib.metadata.Distributions。

inspect?

若模塊中沒(méi)有定義 __loader__ ,則回退至使用 __spec__.loader 。(由 Brett Cannon 在 bpo-42133 中貢獻)

加入了 inspect.get_annotations(),以便安全地對對象中定義的注解進(jìn)行求值。inspect.get_annotations() 也可以正確地解析字符串化的注解。 inspect.get_annotations() 現在應是訪(fǎng)問(wèn)任何 Python 對象注解字典的最佳實(shí)踐;關(guān)于注解最佳用法的更多信息,請參見(jiàn) 對象注解屬性的最佳實(shí)踐。與之關(guān)聯(lián)的, inspect.signature() 、 inspect.Signature.from_callable()inspect.Signature.from_function() 現在也調用 inspect.get_annotations() 來(lái)獲取注解信息。這意味著(zhù) inspect.signature()inspect.Signature.from_callable() 現在也可以解析字符串化的注解了。(由 Larry Hastings 在 bpo-43817 中貢獻)

itertools?

Add itertools.pairwise(). (Contributed by Raymond Hettinger in bpo-38200.)

linecache?

若模塊中沒(méi)有定義 __loader__ ,則回退至使用 __spec__.loader 。(由 Brett Cannon 在 bpo-42133 中貢獻)

os?

為 VxWorks 實(shí)時(shí)操作系統加入 os.cpu_count() 的支持。(由 Peixing Xin 在:issue:41440 中貢獻)

加入一個(gè)新函數 os.eventfd() 及其助手函數,以封裝 Linux 的系統調用 eventfd2 。(由 Christian Heimes 在 bpo-41001 中貢獻)

加入 os.splice(),以便在兩個(gè)文件描述符之間移動(dòng)數據,而無(wú)需在內核地址空間和用戶(hù)地址空間之間進(jìn)行復制,其中一個(gè)文件描述符必須指向某個(gè)管道。(由 Pablo Galindo 在 bpo-41625 中貢獻)

為 macOS 加入 O_EVTONLY 、O_FSYNC 、 O_SYMLINKO_NOFOLLOW_ANY 。(由 Dong-hee Na 在 bpo-43106 中貢獻)

os.path?

現在 os.path.realpath() 可接受一個(gè)關(guān)鍵字參數 strict。 若設為 True ,則在路徑不存在或遭遇循環(huán)符號鏈接時(shí),會(huì )觸發(fā) OSError。 (由 Barney Gale 在 bpo-43757 中貢獻。)

pathlib?

PurePath.parents 加入切片支持。(由Joshua Cannon 貢獻于 bpo-35498

PurePath.parents 加入負數索引支持。(由 Yaroslav Pankovych 貢獻于 bpo-21041

加入 Path.hardlink_to 方法,取代 link_to()。該新方法的參數順序與 symlink_to() 相同。(由 Barney Gale 貢獻于 bpo-39950 中)

現在 pathlib.Path.stat()chmod() 接受一個(gè)關(guān)鍵字參數 follow_symlinks ,以便與 os 模塊中的對應函數保持一致。(由 Barney Gale 貢獻于 bpo-39906

平臺?

加入 platform.freedesktop_os_release(),從標準文件 freedesktop.org os-release 中獲取操作系統標識。(由 Christian Heimes 貢獻于 bpo-28468

pprint?

現在 pprint.pprint() 接受一個(gè)新的關(guān)鍵字參數 underscore_numbers。(由 sblondon 貢獻于 bpo-42914

現在 pprint 可以完美打印 dataclasses.dataclass 實(shí)例。(由 Lewis Gaul 貢獻于 bpo-43080

py_compile?

py_compile' 的命令行界面加入 `--quiet`` 選項。(由 Gregory Schevchenko 貢獻于 bpo-38731

pyclbr?

pyclbr.readline()pyclbr.readline_ex() 返回的結果樹(shù)中的``Function`` 和 Class 對象上增加一個(gè) end_lineno 屬性。與現有的(開(kāi)始)``lineno`` 相匹配。(由 Aviral Srivastava 貢獻于 bpo-38307

shelve?

現在 shelve 模塊在創(chuàng )建打包時(shí),默認采用 pickle.DEFAULT_PROTOCOL,而不是 pickle 協(xié)議 3 。(由 Zackery Spytz 貢獻于 bpo-34204

statistics?

加入 covariance() 、Pearson 的 correlation() 和簡(jiǎn)單的 linear_regression() 函數。(由 Tymoteusz Wo?od?ko 貢獻于 bpo-38490

site?

若模塊中沒(méi)有定義 __loader__ ,則回退至使用 __spec__.loader 。(由 Brett Cannon 在 bpo-42133 中貢獻)

socket?

現在異常 socket.timeoutTimeoutError 的別名。(由 Christian Heimes 在 bpo-42413 中貢獻。)

加入用 IPPROTO_MPTCP 創(chuàng )建 MPTCP 套接字的選項(由 Rui Cunha 貢獻于 bpo-43571

加入 IP_RECVTOS 選項,以便接收服務(wù)類(lèi)型(ToS)或 DSCP/ECN 字段(由 Georg Sauthoff 貢獻于 bpo-44077

ssl?

ssl 模塊要求 OpenSSL 1.1.1 或更新版本。 (由 Christian Heimes 在 PEP 644bpo-43669 中貢獻。)

ssl 模塊已初步支持 OpenSSL 3.0.0 和新選項 OP_IGNORE_UNEXPECTED_EOF。 (由 Christian Heimes 在 bpo-38820, bpo-43794, bpo-43788, bpo-43791, bpo-43799, bpo-43920, bpo-43789bpo-43811 中貢獻。)

現在,已棄用函數和使用已棄用常量會(huì )導致 DeprecationWarning。 ssl.SSLContext.options 默認設置了 OP_NO_SSLv2OP_NO_SSLv3 ,因而設置此標記無(wú)法再次發(fā)出警告了。 棄用部分 列出了已棄用的特性。 (由 Christian Heimes 貢獻于 bpo-43880

現在,ssl 模塊默認設置的安全性提高了。默認情況下,不具備前向安全性或 SHA-1 MAC 的加密算法會(huì )被禁用。二級安全禁止安全性低于 112 位的弱 RSA、DH 和 ECC 密鑰。 SSLContext 默認的最低版本協(xié)議為 TLS 1.2。這些設置是基于 Hynek Schlawack 的研究。(由 Christian Heimes 貢獻于 bpo-43998

已棄用的協(xié)議 SSL 3.0, TLS 1.0 和 TLS 1.1 不再受到官方支持。Python 不會(huì )直接禁用。但 OpenSSL 編譯選項、發(fā)行版配置、廠(chǎng)商補丁和加密套件可能會(huì )阻止握手成功。

ssl.get_server_certificate() 函數加入 timeout 形參。(由 Zackery Spytz 貢獻于 bpo-31870

ssl 模塊用到了堆類(lèi)型和多階段初始化。(由 Christian Heimes 貢獻于 bpo-42333

加入一個(gè)新的校驗標記 VERIFY_X509_PARTIAL_CHAIN。(由 l0x 貢獻于 bpo-40849

sqlite3?

connect/handle() 、 enable_load_extension()load_extension() 加入審計事件。(由 Erlend E. Aasland 貢獻于 bpo-43762

sys?

加入了 sys.orig_argv 屬性:傳給 Python 可執行文件的初始命令行參數列表。(由 Victor Stinner 貢獻于 bpo-23427

添加了 sys.stdlib_module_names,包含標準庫模塊名稱(chēng)的列表。 (由 Victor Stinner 在 bpo-42955 中貢獻。)

_thread?

現在, _thread.interrupt_main() 接受一個(gè)可選的信號值參數進(jìn)行模擬(默認仍為 signal.SIGINT)。(由 Antoine Pitrou 貢獻于 bpo-43356

threading?

加入 threading.gettrace()threading.getprofile() ,分別用于獲取 threading.settrace()threading.setprofile() 設置的函數。(由Mario Corchero 貢獻于 bpo-42251

加入 threading.__excepthook__ ,用于獲取 threading.excepthook() 的初始值,以防被設為一個(gè)差勁或其他的值。(由 Mario Corchero 貢獻于 bpo-42308

traceback?

現在,format_exception() 、 format_exception_only()print_exception() 函數可以接受一個(gè)異常對象,作為唯一的位置參數。(由 Zackery Spytz 和 Matthias Bussonnier 貢獻于 bpo-26389

types?

重新引入 types.EllipsisType 、 types.NoneTypetypes.NotImplementedType 類(lèi),以提供一套新的類(lèi)型,可供類(lèi)型檢查程序解釋。(由 Bas van Beek 貢獻于 bpo-41810

typing?

For major changes, see 有關(guān)類(lèi)型提示的新增特性.

typing.Literal 的行為被改為遵循 PEP 586 并匹配該 PEP 所描述的靜態(tài)類(lèi)型檢查器的行為。

  1. Literal 現在將是去重后的形參。

  2. Literal 對象的相等性比較現在將與順序無(wú)關(guān)。

  3. Literal comparisons now respect types. For example, Literal[0] == Literal[False] previously evaluated to True. It is now False. To support this change, the internally used type cache now supports differentiating types.

  4. 現在,如果 Literal 對象的任何參數都不是 hashable ,在相等性比較時(shí)將引發(fā) TypeError 異常。請注意,在聲明 Literal 時(shí),參數不可哈希不會(huì )拋出錯誤:

    >>>
    >>> from typing import Literal
    >>> Literal[{0}]
    >>> Literal[{0}] == Literal[{False}]
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: unhashable type: 'set'
    

(由 Yurii Karabas 在 bpo-42345 中貢獻。)

加入新函數 typing.is_typeddict(),以?xún)炔繖z查注解是否為 typing.TypedDict。(由 Patrick Reader 貢獻于 bpo-41792

現在,如果 typing.Protocol 的子類(lèi)只聲明了數據變量,那么在用 isinstance 檢查時(shí)會(huì )引發(fā) TypeError,除非是用 runtime_checkable() 裝飾的。以前,這是靜默通過(guò)檢查的。如果用戶(hù)需要運行時(shí)協(xié)議,應該用 runtime_checkable() 裝飾器來(lái)裝飾其子類(lèi)。(由 Yurii Karabas 貢獻于 bpo-38908

Importing from the typing.io and typing.re submodules will now emit DeprecationWarning. These submodules have been deprecated since Python 3.8 and will be removed in a future version of Python. Anything belonging to those submodules should be imported directly from typing instead. (Contributed by Sebastian Rittau in bpo-38291)

unittest?

加入新方法 assertNoLogs() ,以補充現有的 assertLogs()。(由 Kit Yan Choi 貢獻于 bpo-39385

urllib.parse?

Python 3.10 以下版本允許在 urllib.parse.parse_qs()urllib.parse.parse_qsl() 中同時(shí)使用 ;& 作為查詢(xún)參數分隔符。出于安全考慮,并符合 W3C 最新的建議,這已經(jīng)被修改為只允許用一種分隔符,默認值為 &。 這一改變也影響到了 cgi.parse()cgi.parse_multipart(),因為他們內部用到了這些函數。更多細節,請參閱各自的文檔。(由 Adam Goldschmidt 、 Senthil Kumaran 和 Ken Jin 貢獻于 bpo-42967

xml?

xml.sax.handler 模塊中加入一個(gè) LexicalHandler 類(lèi)。(由 Jonathan Gossage 和 Zackery Spytz 貢獻于 bpo-35018

zipimport?

加入 PEP 451 相關(guān)的方法: find_spec() 、zipimport.zipimporter.create_module()zipimport.zipimporter.exec_module()。(由 Brett Cannon 貢獻于 bpo-42131

加入 invalidate_caches() 方法。(由 Desmond Cheong 貢獻于 bpo-14678

性能優(yōu)化?

  • 現在,構造函數 str() 、 bytes()bytearray() 速度更快了(小對象大約提速 30-40%)。(由 Serhiy Storchaka 貢獻于 bpo-41334

  • 現在, runpy 導入的模塊變少了。python3 -m module-name 命令的啟動(dòng)時(shí)間平均加快 1.4 倍。在 Linux 上,Python 3.9 的 python3 -I -m module-name 導入了69個(gè)模塊,而 Python 3.10 只導入了 51個(gè)模塊(少了 18 個(gè))。(由 Victor Stinner 貢獻于 bpo-41006bpo-41718

  • 現在, LOAD_ATTR 指令會(huì )使用新的“單獨操作碼緩存”機制。對于常規屬性大約會(huì )提速 36%,而對于槽位屬性會(huì )加快 44%。(由 Pablo Galindo 和 Yury Selivanov 貢獻于 bpo-42093 ),并由 Guido van Rossum 貢獻于 bpo-42927,基于最初在 PyPy 和 MicroPython 中實(shí)現的思路。)

  • 現在,當用 --enable-optimizations 構建 Python 時(shí),會(huì )在編譯和鏈接命令行中添加 -fno-semantic-interposition。 這會(huì )讓用帶參數 --enable-sharedgcc 構建 Python 解釋器時(shí)提速 30%。詳情請參閱`這篇文章 <https://developers.redhat.com/blog/2020/06/25/red-hat-enterprise-linux-8-2-brings-faster-python-3-8-run-speeds/>`_ 。(由 Victor Stinner 和 Pablo Galindo 貢獻于 bpo-38980

  • bz2 / lzma / zlib 模塊用了新的輸出緩沖區管理代碼,并在 _compression.DecompressReader 類(lèi)中添加``.readall()`` 函數?,F在,bz2 解壓過(guò)程提速了 1.09 倍 ~ 1.17 倍,lzma 解壓快了 1.20 倍 ~ 1.32 倍,GzipFile.read(-1) 快了 1.11 倍 ~ 1.18 倍。(由 Ma Lin 貢獻,由 Gregory P. Smith 審查, bpo-41486

  • 在使用字符串式的注解時(shí),函數的注解字典不再是在函數創(chuàng )建時(shí)建立了。取而代之的是,注解被存儲為一個(gè)字符串元組,而函數對象在需要時(shí)再延遲轉換為注解字典。這一優(yōu)化將定義帶注解函數的CPU時(shí)間減少了一半。(由 Yurii Karabas 和 Inada Naoki 貢獻于 bpo-42202

  • 現在,子串搜索函數,如 str1 in str2str2.find(str1) ,有時(shí)會(huì )采用Crochemore & Perrin的“二路歸并”字符串搜索算法,以避免長(cháng)字符串的二次檢索行為。(由 Dennis Sweeney 貢獻于 bpo-41972

  • _PyType_Lookup() 加入了少許優(yōu)化,以提高類(lèi)型屬性緩存查詢(xún)在常見(jiàn)命中情況下的性能。這使得解釋器的平均速度提高了 1.04 倍。(由 Dino Viehland 貢獻于 bpo-43452

  • 現在,以下內置函數支持更快的 PEP 590 vectorcall 調用約定: map() 、 filter() 、 reversed() 、 bool()float() 。(由 Dong-hee Na 和 Jeroen Demeyer 貢獻于 bpo-43575 、 bpo-43287 、 bpo-41922 、 bpo-41873bpo-41870

  • 通過(guò)移除內部的 RLock ,BZ2File 的性能得以改善。這使得 BZ2File 在面對多個(gè)同時(shí)讀寫(xiě)線(xiàn)程時(shí)變得不再安全,類(lèi)似一直如此的 gziplzma 中的對應類(lèi)。(由 Inada Naoki 貢獻于 bpo-43785

棄用?

移除?

  • 移除了 complex 類(lèi)的特殊方法 __int__, __float__, __floordiv__, __mod__, __divmod__, __rfloordiv__, __rmod____rdivmod__。 它們總是會(huì )引發(fā) TypeError。 (由 Serhiy Storchaka 在 bpo-41974 中貢獻。)

  • ParserBase.error() 方法(來(lái)自私有且未記入文檔的 _markupbase 模塊)已被移除。 html.parser.HTMLParserParserBase 的唯一子類(lèi)并且它的 error() 實(shí)現在 Python 3.5 中已被移除。 (由 Berker Peksag 在 bpo-31844 中貢獻。)

  • 移除了 unicodedata.ucnhash_CAPI 屬性,它是一個(gè)內部 PyCapsule 對象。 相關(guān)聯(lián)的私有 _PyUnicode_Name_CAPI 結構體已被移至內部 C API。 (由 Victor Stinner 在 bpo-42157 中貢獻。)

  • 移除了 parser 模塊,它在 3.9 中由于切換到新的 PEG 解析器而與僅被舊解析器所使用的 C 源文件和頭文件一起被棄用,包括 node.h, parser.h, graminit.hgrammar.h。

  • 移除了公有 C API 函數 PyParser_SimpleParseStringFlags, PyParser_SimpleParseStringFlagsFilename, PyParser_SimpleParseFileFlagsPyNode_Compile,它們在 3.9 中由于切換到新的 PEG 解析器而被棄用。

  • 移除了 formatter 模塊,它在 Python 3.4 中已被棄用。 它相當過(guò)時(shí)、極少被使用,并且未經(jīng)測試。 它最初計劃在 Python 3.6 中移除,但此移除被改為延遲到 Python 2.7 生命期結束之后。 現有用戶(hù)應當將他們用到的所有類(lèi)都拷貝到自己的代碼中。 (由 Dong-hee Na 和 Terry J. Reedy 在 bpo-42299 中貢獻。)

  • 移除了 PyModule_GetWarningsModule() 函數,現在它由于 _warnings 模塊在 2.6 中被轉換為內置模塊而變得沒(méi)有用處。 (由 Hai Shi 在 bpo-42599 中貢獻。)

  • collections 模塊中移除了已被棄用的 容器抽象基類(lèi) 的別名。 (由 Victor Stinner 在 bpo-37324 中貢獻。)

  • loop 形參已從大部分 asyncio高層級 API 中被移除,之前它們在 Python 3.8 中已被棄用。 這一改變的動(dòng)機是多方面的:

    1. 這簡(jiǎn)化了高層級 API。

    2. 高層級 API 中的這些函數自 Python 3.7 起已經(jīng)會(huì )隱式地獲取當前線(xiàn)程正在運行的事件循環(huán)。 在大多數正常使用場(chǎng)景中都沒(méi)有必要向 API 傳入事件循環(huán)。

    3. 在處理不同線(xiàn)程中運行的事件循環(huán)時(shí)傳遞事件循環(huán)特別容易產(chǎn)生錯誤。

    Note that the low-level API will still accept loop. See Python API 的變化 for examples of how to replace existing code.

    (由 Yurii Karabas, Andrew Svetlov, Yury Selivanov 和 Kyle Stanley 在 bpo-42392 中貢獻。)

移植到 Python 3.10?

本節列出了先前描述的更改以及可能需要更改代碼的其他錯誤修正.

Python 語(yǔ)法中的變化?

  • Deprecation warning is now emitted when compiling previously valid syntax if the numeric literal is immediately followed by a keyword (like in 0in x). In future releases it will be changed to syntax warning, and finally to a syntax error. To get rid of the warning and make the code compatible with future releases just add a space between the numeric literal and the following keyword. (Contributed by Serhiy Storchaka in bpo-43833).

Python API 的變化?

  • traceback 模塊中的 format_exception() 、 format_exception_only()print_exception() 函數的 etype 參數已更名為 exc 。(由 Zackery Spytz 和 Matthias Bussonnier 貢獻于 bpo-26389

  • atexit : 在 Python 退出時(shí),若用 atexit.register() 注冊的回調失敗,現在會(huì )記錄其異常。以前,只有部分異常被記錄,最后一個(gè)異??偸潜混o默忽略。(由 Victor Stinner 貢獻于 bpo-42639

  • 現在,泛型 collections.abc.Callable 的類(lèi)型參數扁平化了,類(lèi)似于 typing.Callable 目前的做法。這意味著(zhù) collections.abc.Callable[[int, str], str]__args__ 將為 (int, str, str);而以前是 ([int, str], str)。 通過(guò) typing.get_args()__args__ 訪(fǎng)問(wèn)參數的代碼需要考慮到這一變化。此外,為 collections.abc.Callable 給出無(wú)效參數可能會(huì )引發(fā) TypeError ,而在 Python 3.9 中則可能會(huì )靜默傳入。(由 Ken Jin 貢獻于 bpo-42195

  • 現在,如果給定的形參不是 16 位無(wú)符號整數, socket.htons()socket.ntohs() 會(huì )引發(fā) OverflowError 而非 DeprecationWarning。 (由 Erlend E. Aasland 在 bpo-42393 中貢獻。)

  • The loop parameter has been removed from most of asyncio's high-level API following deprecation in Python 3.8.

    現在如下協(xié)程:

    async def foo(loop):
        await asyncio.sleep(1, loop=loop)
    

    應替換為:

    async def foo():
        await asyncio.sleep(1)
    

    如果 foo() 被特別設計成 運行于當前線(xiàn)程的運行事件循環(huán)中(比如運行在另一個(gè)線(xiàn)程的事件循環(huán)中),請考慮使用 asyncio.run_coroutine_threadsafe() 來(lái)代替。

    (由 Yurii Karabas, Andrew Svetlov, Yury Selivanov 和 Kyle Stanley 在 bpo-42392 中貢獻。)

  • The types.FunctionType constructor now inherits the current builtins if the globals dictionary has no "__builtins__" key, rather than using {"None": None} as builtins: same behavior as eval() and exec() functions. Defining a function with def function(...): ... in Python is not affected, globals cannot be overridden with this syntax: it also inherits the current builtins. (Contributed by Victor Stinner in bpo-42990.)

C API 的變化?

  • 由于換成了新的 PEG 解析程序,C 語(yǔ)言 API 函數``PyParser_SimpleParseStringFlags``、PyParser_SimpleParseStringFlagsFilename、PyParser_SimpleParseFileFlags、PyNode_Compile``以及這些函數用到的類(lèi)型 ``struct _node 已被刪除。

    現在應該用 Py_CompileString() 將源代碼直接編譯為代碼對象。然后可以用 PyEval_EvalCode() 之類(lèi)的東西來(lái)對其求值。

    特別地:

    • PyParser_SimpleParseStringFlagsPyNode_Compile 的調用,可以由 Py_CompileString() 代替。

    • PyParser_SimpleParseFileFlags 沒(méi)有直接替代品。要從 FILE * 參數編譯代碼,需要先用 C 語(yǔ)言讀取文件,然后將結果緩沖區傳給 Py_CompileString()。

    • 要編譯一個(gè) char * 給定文件名的文件,先顯式打開(kāi)該文件,再讀取并進(jìn)行編譯。一種方法是利用 io 模塊的 PyImport_ImportModule() 、 PyObject_CallMethod() 、 PyBytes_AsString()Py_CompileString(),如下圖所示。(省略了聲明和錯誤處理部分)

      io_module = Import_ImportModule("io");
      fileobject = PyObject_CallMethod(io_module, "open", "ss", filename, "rb");
      source_bytes_object = PyObject_CallMethod(fileobject, "read", "");
      result = PyObject_CallMethod(fileobject, "close", "");
      source_buf = PyBytes_AsString(source_bytes_object);
      code = Py_CompileString(source_buf, filename, Py_file_input);
      
    • For FrameObject objects, the f_lasti member now represents a wordcode offset instead of a simple offset into the bytecode string. This means that this number needs to be multiplied by 2 to be used with APIs that expect a byte offset instead (like PyCode_Addr2Line() for example). Notice as well that the f_lasti member of FrameObject objects is not considered stable: please use PyFrame_GetLineNumber() instead.

CPython 字節碼的改變?

  • MAKE_FUNCTION 指令現在可以接受一個(gè)字典或一個(gè)字符串元組作為函數的標注。 (由 Yurii Karabas 和 Inada Naoki 在 bpo-42202 中貢獻。)

編譯版的變化?

  • PEP 644 :Python 現在要求 OpenSSL 1.1.1 以上版本。不再支持 OpenSSL 1.0.2。(由 Christian Heimes 貢獻于 bpo-43669

  • 編譯 Python 現在需要用到 C99 函數 snprintf()vsnprintf() 。(由 Victor Stinner 貢獻于 bpo-36020

  • sqlite3 requires SQLite 3.7.15 or higher. (Contributed by Sergey Fedoseev and Erlend E. Aasland in bpo-40744 and bpo-40810.)

  • 現在, atexit 模塊必須編譯為內置模塊。(由 Victor Stinner 貢獻于 bpo-42639

  • configure 腳本中加入 --disable-test-modules 選項:不編譯也不安裝 test 模塊。(由 Xavier de Gaye、Thomas Petazzoni 和 Peixing Xin 貢獻于 bpo-27640

  • ./configure 腳本中加入 --with-wheel-pkg-dir=PATH 選項。如果指定了該選項, ensurepip 模塊會(huì )在該目錄下查找 setuptoolspip 包:如果兩者都存在,就會(huì )使用這些包,而不是surepip 綁定的包。

    某些 Linux 發(fā)行版的打包策略建議不要綁定依賴(lài)關(guān)系。比如 Fedora 在``/usr/share/python-wheels/`` 目錄下安裝 wheel 包,而不安裝``ensurepip._bundled`` 包。

    (由 Victor Stinner 貢獻于 bpo-42856

  • 增加了新的 configure --without-static-libpython 選項 ,用于標明不編譯 libpythonMAJOR.MINOR.a 靜態(tài)庫并且不安裝 python.o 對象文件。

    (由 Victor Stinner 在 bpo-43103 中貢獻。)

  • The configure script now uses the pkg-config utility, if available, to detect the location of Tcl/Tk headers and libraries. As before, those locations can be explicitly specified with the --with-tcltk-includes and --with-tcltk-libs configuration options. (Contributed by Manolis Stamatogiannakis in bpo-42603.)

  • configure 腳本加入 --with-openssl-rpath 選項。該選項簡(jiǎn)化了用定制版本 OpenSSL 編譯 Python 的過(guò)程,例如 ./configure --with-openssl=/path/to/openssl --with-openssl-rpath=auto。(由 Christian Heimes 貢獻于 bpo-43466

C API 的變化?

PEP 652:穩定版 ABI 的維護?

現在,用于擴展模塊或嵌入 Python 的穩定版 ABI (應用程序二進(jìn)制接口)已有顯式的定義。 C API Stability 描述了 C API 和 ABI 穩定性保證和穩定版 ABI 的最佳實(shí)踐。

(由 Petr Viktorin 在 PEP 652bpo-43795 中貢獻。).)

新的特性?

  • 現在 PyNumber_Index() 的結果一定是 int 類(lèi)型。此前可能是 int 的子類(lèi)實(shí)例。(由 Serhiy Storchaka 貢獻于 bpo-40792

  • Add a new orig_argv member to the PyConfig structure: the list of the original command line arguments passed to the Python executable. (Contributed by Victor Stinner in bpo-23427.)

  • 加入宏 PyDateTime_DATE_GET_TZINFO()PyDateTime_TIME_GET_TZINFO() ,用于訪(fǎng)問(wèn) datetime.datetimedatetime.time 對象的 tzinfo 屬性。 (由 Zackery Spytz 貢獻于 bpo-30155

  • 加入 PyCodec_Unregister() 函數,用于注銷(xiāo)編解碼器檢索函數。(由 Hai Shi 貢獻于 bpo-41842

  • 加入 PyIter_Send() 函數,可不觸發(fā) StopIteration 異常地向迭代器發(fā)送數據。(由 Vladimir Matveev 貢獻于 bpo-41756

  • 受限 C API 中加入了 PyUnicode_AsUTF8AndSize() 。(由 Alex Gaynor 貢獻于 bpo-41784

  • 加入 PyModule_AddObjectRef() 函數:類(lèi)似于 PyModule_AddObject() 但在成功后不會(huì )偷取參數對象的引用計數。(由 Victor Stinner 貢獻于 bpo-1635741

  • 加入 Py_NewRef()Py_XNewRef() 函數,用于遞增指定對象的引用計數并返回該對象。(由 Victor Stinner 貢獻于 bpo-42262

  • 現在, PyType_FromSpecWithBases()PyType_FromModuleAndSpec() 函數可接受一個(gè)類(lèi)作為 bases 參數。(由 Serhiy Storchaka 貢獻于 bpo-42423

  • PyType_FromModuleAndSpec() 函數現在接受 NULL tp_doc 槽位。 (由 Hai Shi 在 bpo-41832 中貢獻。)

  • PyType_GetSlot() 函數現在可以接受 靜態(tài)類(lèi)型。 (由 Hai Shi 和 Petr Viktorin 在 bpo-41073 中貢獻。)

  • 新增 PySet_CheckExact() 函數到 C-API 用于檢查一個(gè)對象是否是 set 的實(shí)例但不是其子類(lèi)型的實(shí)例。 (由 Pablo Galindo 在 bpo-43277 中貢獻。)

  • 增加了 PyErr_SetInterruptEx(),它允許傳入一個(gè)信號序號用于進(jìn)行模擬。 (由 Antoine Pitrou 在 bpo-43356 中貢獻。)

  • 現在,Python 以調試模式編譯 時(shí)也支持受限 C API 的使用了(需先定義 Py_DEBUG 宏)。在受限 C API 中,如果 Python 是以調試模式編譯的,且 Py_LIMITED_API 宏以 Python 3.10 以上版本為目標,那么現在 Py_INCREF()Py_DECREF() 函數實(shí)現為非透明的函數調用,而非直接訪(fǎng)問(wèn) PyObject.ob_refcnt 成員。在調試模式下支持受限 C API 成為可能,是因為自 Python 3.8 起 PyObject 結構體在發(fā)布模式和調試模式下是相同的(參見(jiàn) bpo-36465 )。

    --with-trace-refs 特殊編譯方式下(Py_TRACE_REFS 宏),仍不支持使用受限 C API 。(由 Victor Stinner 貢獻于 bpo-43688

  • 加入 Py_Is(x, y) 函數,用于測試 x 對象是否是 y 對象,等價(jià)于 Python 中的 x is y。還加入了 Py_IsNone() 、 Py_IsTrue() 、 Py_IsFalse() 函數,分別用于測試某對象是否為 None 單例、True 單例或 False 單例。(由 Victor Stinner 貢獻于 bpo-43753

  • 新增由 C 代碼控制垃圾回收器的函數: PyGC_Enable(), 、PyGC_Disable() 、 PyGC_IsEnabled()。這些函數允許從 C 代碼激活、停止和查詢(xún)垃圾回收器的狀態(tài),而不必導入 gc 模塊。

  • 新增 Py_TPFLAGS_DISALLOW_INSTANTIATION 類(lèi)型標記,用于禁止創(chuàng )建類(lèi)型實(shí)例。(由 Victor Stinner 貢獻于 bpo-43916

  • 新增 Py_TPFLAGS_IMMUTABLETYPE 類(lèi)型標記,用于創(chuàng )建不可變類(lèi)型對象:類(lèi)型的屬性不可設置或刪除。(由 Victor Stinner 和 Erlend E. Aasland 貢獻于 bpo-43908

移植到 Python 3.10?

  • 現在必須定義 PY_SSIZE_T_CLEAN 才能使用 PyArg_ParseTuple()Py_BuildValue(),該格式會(huì )使用 #: es#, et#, s#, u#, y#, z#, U#Z#。 參見(jiàn) 解析參數和構造值 以及 PEP 353。 (由 Victor Stinner 在 bpo-40943 中貢獻。)

  • 由于 Py_REFCNT() 已改為內聯(lián)靜態(tài)函數,Py_REFCNT(obj) = new_refcnt 必須換成 Py_SET_REFCNT(obj, new_refcnt): 參見(jiàn) Py_SET_REFCNT() (自 Python 3.9 起提供)。為保持向下兼容,可用此宏:

    #if PY_VERSION_HEX < 0x030900A4
    #  define Py_SET_REFCNT(obj, refcnt) ((Py_REFCNT(obj) = (refcnt)), (void)0)
    #endif
    

    (由 Victor Stinner 在 bpo-39573 中貢獻。)

  • 由于歷史原因,曾經(jīng)允許調用 PyDict_GetItem() 時(shí)不帶 GIL 。 現在則不行了。(由 Victor Stinner 貢獻于 bpo-40839

  • 現在, PyUnicode_FromUnicode(NULL, size)PyUnicode_FromStringAndSize(NULL, size) 會(huì )引發(fā) DeprecationWarning。 請利用 PyUnicode_New() 獲得不帶初始數據的 Unicode 對象。(由 Inada Naoki 貢獻于 bpo-36346

  • 私有結構體 _PyUnicode_Name_CAPI (PyCapsule API unicodedata.ucnhash_CAPI )已被移入內部 C API。(由 Victor Stinner 貢獻于 bpo-42157

  • 現在,若是在 Py_Initialize() 之前去調用(在 Python 被初始化之前), Py_GetPath(), Py_GetPrefix() 、 Py_GetExecPrefix() 、 Py_GetProgramFullPath() 、 Py_GetPythonHome()Py_GetProgramName() 將返回 NULL。 請用新的 Python 初始化配置 API 來(lái)獲取 Python 路徑配置。(由 Victor Stinner 貢獻于 bpo-42260

  • PyList_SET_ITEM() 、 PyTuple_SET_ITEM()PyCell_SET() 不可再用作左值或右值。例如,現在``x = PyList_SET_ITEM(a, b, c)`` 和 PyList_SET_ITEM(a, b, c) = x 會(huì )失敗并提示編譯器錯誤。 這可以防止 if (PyList_SET_ITEM (a, b, c) < 0) ... 之類(lèi)的檢測發(fā)生問(wèn)題。(由 Zackery Spytz 和 Victor Stinner 貢獻于 bpo-30459

  • 非受限 API 文件 odictobject.h 、 parser_interface.h 、 picklebufobject.h 、 pyarena.h 、 pyctype.h、 pydebug.h、 pyfpe.hpytime.h 已被移至 Include/cpython 目錄。這些文件不能被直接包含,因為 Python.h 中已包含過(guò)了: Include 文件。 如果已被直接包含,請考慮改為包含 Python.h。(由 Nicholas Sim 貢獻于 bpo-35134

  • 請用 Py_TPFLAGS_IMMUTABLETYPE 類(lèi)型標記來(lái)創(chuàng )建不可變對象。 不要依賴(lài) Py_TPFLAGS_HEAPTYPE 來(lái)確定類(lèi)型對象是否可變;請改為檢查是否設置了 Py_TPFLAGS_IMMUTABLETYPE。(由 Victor Stinner 和 Erlend E. Aasland 貢獻于 bpo-43908

  • 未記入文檔的函數 Py_FrozenMain 已從受限 API 中移除。該函數主要適用于 Python 的定制版。(由 Petr Viktorin 貢獻于 bpo-26241

棄用?

  • 現在 PyUnicode_InternImmortal() 函數已被棄用,并將在 Python 3.12 中移除:請改用 PyUnicode_InternInPlace()。(由 Victor Stinner 貢獻于 bpo-41692

移除?

  • 移除了 Py_UNICODE_str* 函數,它被用于控制 Py_UNICODE* 字符串。 (由 Inada Naoki 在 bpo-41123 中貢獻。)

  • 移除了 PyUnicode_GetMax()。 請遷移到新的 (PEP 393) API。 (由 Inada Naoki 在 bpo-41103 中貢獻。)

  • 移除了 PyLong_FromUnicode()。 請遷移到 PyLong_FromUnicodeObject()。 (由 Inada Naoki 在 bpo-41103 中貢獻。)

  • 移除了 PyUnicode_AsUnicodeCopy()。 請使用 PyUnicode_AsUCS4Copy()PyUnicode_AsWideCharString() (由 Inada Naoki 在 bpo-41103 中貢獻。)

  • 移除了 _Py_CheckRecursionLimit 變量:它已被 PyInterpreterState 結構體的 ceval.recursion_limit 所取代。 (由 Victor Stinner 在 bpo-41834 中貢獻。)

  • 移除了未記入文檔的宏 Py_ALLOW_RECURSIONPy_END_ALLOW_RECURSION 以及 PyInterpreterState 結構體的 recursion_critical 字段。 (由 Serhiy Storchaka 在 bpo-41936 中貢獻。)

  • 移除了未記入文檔的 PyOS_InitInterrupts() 函數。Python 初始化時(shí)已隱式安裝了信號處理 handler:參見(jiàn) PyConfig.install_signal_handlers。(由 Victor Stinner 貢獻于 bpo-41713

  • 移除了 PyAST_Validate() 函數。不能再使用公有 C API 來(lái)構建 AST 對象(mod_ty 類(lèi)型)了。該函數已不屬于受限 C API(PEP 384 )。(由 Victor Stinner 貢獻于 bpo-43244

  • 移除了 symtable.h 頭文件及未寫(xiě)入文檔的函數:

    • PyST_GetScope()

    • PySymtable_Build()

    • PySymtable_BuildObject()

    • PySymtable_Free()

    • Py_SymtableString()

    • Py_SymtableStringObject()

    Py_SymtableString() 函數誤為穩定版 ABI 卻無(wú)法使用,因為 symtable.h 頭文件不屬于受限 C API。

    請改用 Python symtable 模塊。 (由 Victor Stinner 在 bpo-43244 中貢獻。)

  • PyOS_ReadlineFunctionPointer() 已從受限 C API 頭文件和 python3.dll 中移除,此 dll 為 Windows 中的穩定版 ABI 庫。由于該函數可接受一個(gè) FILE* 參數,所以無(wú)法保證其 ABI 穩定性。(由 Petr Viktorin 貢獻于 bpo-43868

  • 移除了 ast.h, asdl.hPython-ast.h 頭文件。 這些函數未入文檔且不屬于受限 C API。這些頭文件中定義的大多數名稱(chēng)都不帶 Py 前綴,因此可能會(huì )造成命名沖突。比如 Python-ast.h 定義了一個(gè) Yield 宏,就會(huì )與另一個(gè)Windows <winbase.h> 頭文件中的 Yield 沖突。請改用 Python ast 模塊。(由 Victor Stinner 貢獻于 bpo-43244

  • 移除了用到 struct _mod 類(lèi)型的編譯器和解析器函數,因為公共的 AST C API 已被移除:

    • PyAST_Compile()

    • PyAST_CompileEx()

    • PyAST_CompileObject()

    • PyFuture_FromAST()

    • PyFuture_FromASTObject()

    • PyParser_ASTFromFile()

    • PyParser_ASTFromFileObject()

    • PyParser_ASTFromFilename()

    • PyParser_ASTFromString()

    • PyParser_ASTFromStringObject()

    這些函數未入文檔且不屬于受限 C API。(由 Victor Stinner 貢獻于 bpo-43244

  • 移除了包含下列函數的頭文件 pyarena.h

    • PyArena_New()

    • PyArena_Free()

    • PyArena_Malloc()

    • PyArena_AddPyObject()

    這些函數未記入文檔,且不屬于受限 C API,僅由編譯器內部使用。(由 Victor Stinner 貢獻于 bpo-43244

  • The PyThreadState.use_tracing member has been removed to optimize Python. (Contributed by Mark Shannon in bpo-43760.)