Python 3.10 有什麼新功能
************************

編輯者:
   Pablo Galindo Salgado

本文介紹了 Python 3.10 與 3.9 相比的新功能。Python 3.10 於 2021 年 10
月 4 日發布。有關完整詳細資訊，請參閱 changelog。


摘要 -- 發布重點
================

新增語法特性：

* **PEP 634**，結構模式匹配 (Structural Pattern Matching)：規範

* **PEP 635**，結構模式匹配：動機和基本原理

* **PEP 636**，結構模式匹配：教學

* bpo-12782，現在正式允許帶括號的情境管理器 (context manager)。

標準函式庫中的新功能：

* **PEP 618**，新增可選的長度檢查到 zip。

直譯器改進：

* **PEP 626**，用於除錯和其他工具的精確列號。

新的 typing 功能：

* **PEP 604**，允許將聯集型別 (union types) 寫為 X | Y

* **PEP 612**，參數規範變數 (Parameter Specification Variables)

* **PEP 613**，顯式型別別名 (Explicit Type Aliases)

* **PEP 647**，使用者定義的型別防護 (User-Defined Type Guards)

重要的棄用、刪除或限制：

* **PEP 644**，需要 OpenSSL 1.1.1 或更高版本

* **PEP 632**，棄用 distutils 模組。

* **PEP 623**，棄用並準備刪除 PyUnicodeObject 中的 wstr 成員。

* **PEP 624**，刪除 Py_UNICODE 編碼器 API

* **PEP 597**，新增可選的 EncodingWarning


新功能
======


帶括號的情境管理器
------------------

現在支援使用成對的括號來將多個情境管理器以數行表示。這允許了與過去的引
入陳述式 (import statement) 類似的方法來格式化一組多行的情境管理器集合
。例如，以下範例現在都是有效的：

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

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

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

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

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

也可以在封閉群組的末尾使用逗號：

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

此新語法使用新剖析器的非 LL(1) 功能。檢查 **PEP 617** 了解更多詳細資訊
。

（由 Guido van Rossum、Pablo Galindo 和 Lysandros Nikolaou 在
bpo-12782 和 bpo-40334 中貢獻。）


更好的錯誤訊息
--------------


SyntaxErrors
~~~~~~~~~~~~

當剖析包含未成對括號或方括號的程式碼時，直譯器現在會包含未成對括號的位
置，而不是顯示 *SyntaxError: unexpected EOF while parsing* 或指向某些
不正確的位置。例如，以下程式碼（注意未閉合的 "{" ）：

   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()

以前版本的直譯器會在奇怪的地方顯示有語法錯誤：

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

但在 Python 3.10 中，會發出一個資訊更豐富的錯誤：

   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

同樣地，涉及未成對字串字面值（單引號和三引號）的錯誤現在會指向字串的開
頭，而不是報告 EOF/EOL。

這些改進是受到 PyPy 直譯器的啟發。

（由 Pablo Galindo 在 bpo-42864 和 Batuhan Taskaya 在 bpo-40176 中貢獻
。）

直譯器引發的 "SyntaxError" 例外現在會突顯 (highlight) 構成語法錯誤之運
算式的完整錯誤範圍，而不僅是檢測到問題的位置。如此一來，過去（像
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

此改進由 Pablo Galindo 在 bpo-43914 中貢獻。

已合併了大量針對 "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 中貢獻。）

* 容器字面值 (collection literals) 中和運算式之間缺少逗號：

     >>> 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 中貢獻。）

* 不帶括號的多個例外型別：

     >>> 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 中貢獻。）

* 沒有 "except" 或 "finally" 區塊的 "try" 區塊：

     >>> 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 中貢獻。）


IndentationErrors
~~~~~~~~~~~~~~~~~

許多 "IndentationError" 例外現在支援更多關於哪種區塊需要縮進的情境，包
括陳述式的位置：

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


AttributeErrors
~~~~~~~~~~~~~~~

當印出 "AttributeError" 時，"PyErr_Display()" 將提供引發例外的物件中類
似屬性名稱的建議：

   >>> 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()" 來顯示錯誤（可能為了要使用其他
  自定義錯誤顯示函式），則此操作將不起作用。這是 IPython 等某些 REPL
  中的常見狀況。


NameErrors
~~~~~~~~~~

當印出直譯器引發的 "NameError" 時，"PyErr_Display()" 將在引發例外的函
式中提供類似變數名稱的建議：

   >>> 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()" 來顯示錯誤，則此操作將不起作用
  ，如果使用其他自定義錯誤顯示函式，則可能會發生這種情況。這是 IPython
  等某些 REPL 中的常見場景。


PEP 626：用於除錯和其他工具的精確列號
-------------------------------------

PEP 626 為除錯、分析 (profiling) 和覆蓋 (coverage) 工具帶來了更精確、
更可靠的列號 (line numbers)。為所有已執行的程式碼列且僅針對已執行的程
式碼行產生具有正確列號的追蹤事件。

The "f_lineno" attribute of frame objects will always contain the
expected line number.

The "co_lnotab" attribute of code objects is deprecated and will be
removed in 3.12. Code that needs to convert from offset to line number
should use the new "co_lines()" method instead.


PEP 634：結構模式匹配
---------------------

已新增結構模式匹配 (structural pattern matching)，其形式為具有關聯操作
之模式的 *match 陳述式* 和 *case 陳述式*。模式由序列、對映、原始資料型
別 (primitive data types) 以及類別實例組成。模式匹配使程式能夠從複雜的
資料型別中提取資訊，在資料結構上進行分支，並根據不同形式的資料應用特定
的操作。


語法和操作
~~~~~~~~~~

模式匹配的通用語法是：

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

match 陳述式採用一個運算式，並將其值與作為一個或多個 case 區塊給出的連
續模式進行比較。具體來說，模式匹配是透過以下方式進行操作：

1. 使用具有型態 (type) 和特徵 (shape) 的資料 (主語 "subject")

2. "match" 陳述式中 "subject" 的求值 (evaluating)

3. 從上到下將主語與 "case" 陳述式中的每個模式進行比較，直到確認匹配。

4. 執行與已確認匹配模式對應的操作

5. 如果未確認完全匹配，則最後一種情況，即萬用字元 "_" （如果有提供）將
   作為匹配到的情況。如未有任何匹配且不存在萬用字元的 case，則整個
   match 區塊會是個無操作 (no-op)。


宣告式方法 (Declarative approach)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

讀者可能會透過使用 C、Java 或 JavaScript（以及許多其他語言）中的
switch 陳述式將主語（資料物件）與字面值 (literal)（模式）進行匹配的簡
單範例來了解模式匹配。 switch 語句通常用於將物件/運算式與包含字面值的
case 陳述式進行比較。

更強大的模式匹配範例可以在 Scala 和 Elixir 等語言中找到。對於結構模式
匹配，該方法是「宣告式的 (declarative)」，並且明確地說明了資料匹配的條
件（模式）。

雖然使用巢狀 "if" 陳述式的「命令式 (imperative)」指令系列可用於完成類
似於結構模式匹配的操作，但它不如「聲明式 (declarative)」方法清晰。相反
地，「聲明式」方法規定了匹配所需滿足的條件，並且因其明確表達模式而更具
可讀性。雖然結構模式匹配可以用其最簡單的形式達成，將變數與 case 陳述式
中的字面值進行比較，但它對 Python 的真正價值在於它對主語的型態和特徵的
處理。


簡單模式：與字面值匹配
~~~~~~~~~~~~~~~~~~~~~~

讓我們將此範例視為最簡單形式的模式匹配：一個值（主語）與多個文字（模式
）匹配。在下面的範例中，"status" 是匹配陳述式的主語。這些模式是每個
case 陳述式，其中文字表示請求狀態程式碼。與案例相關的操作在匹配後執行
：

   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"

如果上面的函式傳遞了 418 "status"，則回傳 "I'm a teapot"。如果上面的函
式傳遞了 500 "status"，則帶有 "_" 的 case 語句將作為萬用字元進行匹配，
並回傳 "Something's wrong with the internet"。請注意最後一個區塊：變數
名稱 "_" 充當 *萬用字元* 並確保主語始終匹配。"_" 的使用是可選的。

你可以使用 "|" ("or") 將多個字面值組合在一個模式中：

   case 401 | 403 | 404:
       return "Not allowed"


沒有萬用字元 (wildcard) 的行為
""""""""""""""""""""""""""""""

如果我們透過刪除最後一個 case 區塊來修改上面的範例，則範例將變為：

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

如果在 case 陳述式中不使用 "_"，則可能不存在匹配項目。如果不存在匹配項
目，則該行為是無操作 (no-op)。例如，如果 "status" 為 500，則不會有任何
操作。


具有字面值和變數的模式
~~~~~~~~~~~~~~~~~~~~~~

模式看起來就像解包賦值 (unpacking assignment)，並且模式可用於繫結
(bind) 變數。在此範例中，可以將資料點解包為其 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")

第一個模式有兩個字面值 "(0, 0)"，並且可以被認為是上面顯示的字面值模式
的擴充。接下來的兩個模式組合了一個字面值和一個變數，並且變數*繫結*來自
主語（"point"）的值。第四個模式捕獲兩個值，這使得它在概念上類似於解包
賦值 "(x, y) = point"。


模式和類別
~~~~~~~~~~

如果你使用類別來建構資料，則可以用類別名稱與後面的引數列表組合成的建構
函式作為模式。該模式能夠將類別屬性捕獲到變數中：

   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")


具有位置參數的模式
""""""""""""""""""

你可以將位置參數與一些會為其屬性排序的內建類別（例如 dataclasses）一起
使用。你還可以通過在類別中設定 "__match_args__" 特殊屬性來定義模式中屬
性的特定位置。如果它被設定為 ("x", "y")，則以下模式都是等效的（且都將
"y" 屬性繫結到 "var" 變數）：

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


巢狀模式
~~~~~~~~

模式可以任意巢套。例如，如果我們的資料是一個簡短的座標點列表，則可以這
樣匹配：

   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.")


複雜模式和萬用字元
~~~~~~~~~~~~~~~~~~

到目前為止，範例在最後一個 case 陳述式中單獨使用了 "_"。萬用字元可以用
在更複雜的模式中，像是 "('error', code, _)"。例如

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

在上述情況下，值像是 ('error', code, 100) 和 ('error', code, 800) 的
"test_variable" 將會成功匹配。


Guard
~~~~~

我們可以在模式中新增一個 "if" 子句，稱為 "guard"。如果 guard 為 false
，則 "match" 會繼續嘗試下一個 case 區塊。請注意，值的捕獲發生在 guard
的求值 (evaluate) 之前：

   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.")


其他主要功能
~~~~~~~~~~~~

其他幾個主要功能：

* 與賦值的解包一樣，tuple 和 list 模式具有完全相同的含義，並且實際上匹
  配任意序列。從技術上來說，主語必須是一個序列。因此，一個重要的例外是
  模式不會去匹配疊代器。另外，為了防止常常出錯，序列模式也不會去匹配字
  串。

* 序列模式支援萬用字元："[x, y, *rest]" 和 "(x, y, *rest)" 與解包賦值
  中的萬用字元類似。 "*" 後面的名稱也可能是 "_"，因此 "(x, y, *_)" 會
  匹配至少兩個項目的序列，且不繫結其餘項目。

* 對映模式： "{"bandwidth": b, "latency": l}" 從字典中捕獲
  ""bandwidth"" 和 ""latency"" 值。與序列模式不同，額外的鍵將被忽略。
  也支援萬用字元 "**rest"。（但是 "**_" 是多餘的，所以是不允許的。）

* 可以使用 "as" 關鍵字捕獲子模式：

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

  這將繫結 x1、y1、x2、y2，如同沒有 "as" 子句的情況下所預期的，並將 p2
  繫結到主語的整個第二項目。

* 大多數字面值都是通過相等進行比較的。然而，單例 "True"、"False" 和
  "None" 是按標識值 (identity) 來進行比較的。

* 附名常數 (named constant) 可以在模式中使用。這些附名常數必須有帶有點
  的名稱 (dotted name)，以防止常數被直譯為捕獲的變數：

     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 :(")

有關完整規範，請參閱 **PEP 634**。動機和基本原理位於 **PEP 635** 中，
較完整的教學位於 **PEP 636** 中。


可選的 "EncodingWarning" 和 "encoding="locale"" 選項
----------------------------------------------------

"TextIOWrapper" 和 "open()" 的預設編碼取決於平台和區域設定。由於大多數
Unix 平台都使用 UTF-8，因此在打開 UTF-8 檔案（例如 JSON、YAML、TOML、
Markdown）時省略 "encoding" 選項是個常見的 bug，例如：

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

為了發現這種錯誤，新增了一個可選的 "EncodingWarning"。當
"sys.flags.warn_default_encoding" 為 true 且使用特定於語言環境的預設編
碼時，會發出該信號。

新增 "-X warn_default_encoding" 選項和 "PYTHONWARNDEFAULTENCODING" 來
啟用警告。

更多資訊請見 文字編碼。


與型別提示相關的新功能
======================

本節介紹影響 **PEP 484** 型別提示和 "typing" 模組的主要更改。


PEP 604：新型聯集運算子
-----------------------

引入了一種新的聯集運算子，該運算子啟用像是 "X | Y" 的語法。這提供了一
種在型別提示中更清晰的方式來表達「型別 X 或型別 Y」，來取代使用
"typing.Union"。

在以前版本的 Python 中，要使用接受多種型別參數之型別提示的函式，要使用
"typing.Union"：

   def square(number: Union[int, float]) -> Union[int, float]:
       return number ** 2

現在可以用更簡潔的方式編寫型別提示：

   def square(number: int | float) -> int | float:
       return number ** 2

這種新語法也接受作為 "isinstance()" 和 "issubclass()" 的第二個引數：

   >>> isinstance(1, int | str)
   True

更多資訊請見 Union Type 與 **PEP 604**。

（由 Maggie Moss 和 Philippe Prados 在 bpo-41428 中貢獻，由 Yurii
Karabas 和 Serhiy Storchaka 在 bpo-44490 中補充。）


PEP 612：參數規範變數
---------------------

"typing" 模組中新增了兩個新選項，用於改進為 **PEP 484** "Callable" 的
靜態型別檢查器 (static type checker) 所提供的資訊。

第一個是參數規範變數 (parameter specification variable)。它們用於將一
個可呼叫物件的參數型別轉發到另一個可呼叫物件 -- 這是高階函式和裝飾器中
常見的模式。使用範例可以在 "typing.ParamSpec" 中找到。在過去是沒有簡單
的方法可以如此精確地來為參數型別的依賴關係做型別註釋。

第二個選項是新的 "Concatenate" 運算子。它與參數規範變數結合使用，來對
一個高階、會新增或刪除另一個可呼叫物件參數的可呼叫物件進行型別註釋。使
用範例可以在 "typing.Concatenate" 中找到。

請參閱 "typing.Callable"、"typing.ParamSpec"、"typing.Concatenate"、
"typing.ParamSpecArgs"、"typing.ParamSpecKwargs" 和 **PEP 612** 以了解
更多詳情。

（由 Ken Jin 在 bpo-41559 中貢獻、Jelle Zijlstra 在 bpo-43783 中進行了
小幅改進。PEP 由 Mark Mendoza 編寫。）


PEP 613：型別別名 (TypeAlias)
-----------------------------

**PEP 484** 引入了型別別名 (type aliases) 的概念，只要求它們是最高階、
未註釋的賦值 (top-level unannotated assignments)。這種簡單性有時使型別
檢查器難以區分型別別名和普通賦值，尤其是在涉及傳遞參照 (reference) 或
無效型別時。比較如下：

   StrCache = 'Cache[str]'  # a type alias
   LOG_PREFIX = 'LOG[DEBUG]'  # a module constant

現在 "typing" 模組有一個特殊值 "TypeAlias"，它可以讓你更明確地宣告型別
別名：

   StrCache: TypeAlias = 'Cache[str]'  # a type alias
   LOG_PREFIX = 'LOG[DEBUG]'  # a module constant

更多資訊請見 **PEP 613**。

（由 Mikhail Golubev 在 bpo-41923 中貢獻。）


PEP 647：使用者定義的型別防護
-----------------------------

"TypeGuard"（型別防護）已新增到 "typing" 模組中，用以註釋型別防護函式
並改進在型別窄縮 (type narrowing) 期間提供給靜態型別檢查器的資訊。有關
更多資訊，請參閱 "TypeGuard" 的文件和 **PEP 647**。

（由 Ken Jin 和 Guido van Rossum 在 bpo-43766 中貢獻。PEP 由 Eric
Traut 編寫。）


其他語言變化
============

* "int" 型別有一個新方法 "int.bit_count()"，回傳給定整數的二進位展開式
  中 1 的數量，也稱為總體計數 (population count)。（由 Niklas Fiekas
  在 bpo-29882 中貢獻。）

* "dict.keys()"、"dict.values()" 和 "dict.items()" 回傳的視圖 (view)
  現在都有一個 "mapping" 屬性，該屬性提供 "types.MappingProxyType" 包
  裝原始的字典物件。（由 Dennis Sweeney 在 bpo-40890 中貢獻。）

* **PEP 618**："zip()" 函式現在有一個可選的 "strict" 旗標，用於要求所
  有可疊代物件具有相同的長度。

* 採用整數引數的內建函式和擴充函式不再接受 "Decimal"、"Fraction" 以及
  其他只能在有損失的情況下轉換為整數的物件（例如有 "__int__()" 方法，
  但沒有 "__index__()" 方法）。（由 Serhiy Storchaka 在 bpo-37999 中貢
  獻。）

* If "object.__ipow__()" returns "NotImplemented", the operator will
  correctly fall back to "object.__pow__()" and "object.__rpow__()" as
  expected. (Contributed by Alex Shkop in bpo-38302.)

* 現在可以在集合字面值 (set literals) 和集合綜合運算 (set
  comprehensions) 以及序列索引（但不能是切片）中使用不帶括號的賦值運算
  式 (assignment expressions)。

* 函式有一個新的 "__builtins__" 屬性，用於在執行函式時查找內建符號，而
  不是查找 "__globals__['__builtins__']" 。如果
  "__globals__["__builtins__"]" 存在，則屬性會以此做初始化，否則從當前
  內建物件 (builtins) 初始化。（由 Mark Shannon 在 bpo-42990 中貢獻。
  ）

* 新增兩個內建函式 -- "aiter()" 和 "anext()"，分別為 "iter()" 和
  "next()" 提供非同步的對應函式。（由 Joshua Bronson、Daniel Pope 和
  Justin Wang 在 bpo-31861 中貢獻。）

* 靜態方法 ("@staticmethod") 和類別方法 ("@classmethod") 現在繼承方法
  屬性 ("__module__", "__name__", "__qualname__", "__doc__",
  "__annotations__") 並有一個新的 "__wrapped__" 屬性。此外，靜態方法現
  在可以像是常規函式般呼叫。（由 Victor Stinner 在 bpo-43682 中貢獻。
  ）

* 複雜目標（除 **PEP 526** 定義的 "simple name" 目標之外的所有內容）的
  註釋不再使用 "from __future__ import comments" 造成任何執行環境
  (runtime) 影響。（由 Batuhan Taskaya 在 bpo-42737 中貢獻。）

* 類別和模組物件現在會根據需求來延遲建立 (lazy-create) 空的註釋字典
  (annotations dicts)。註釋字典存儲在物件的 "__dict__" 中以達成向後相
  容性。這改進了 "__annotations__" 使用方式的最佳實踐方法；有關更多資
  訊，請參閱 Annotations Best Practices。（由 Larry Hastings 在
  bpo-43901 中貢獻。）

* 附名運算式或由 "yield"、"yield from"、"await" 組成的註釋現在在 "from
  __future__ import comments" 下被禁止，因為它們有些不預期的行為。（由
  Batuhan Taskaya 在 bpo-42725 中貢獻。）

* 未繫結變數 (unbound variable)、"super()" 和其他可能會改變處理註釋之
  符號表 (symbol table) 的運算式，現在在 "from __future__ import
  comments" 下變得無效。（由 Batuhan Taskaya 在 bpo-42725 中貢獻。）

* "float" 型別和 "decimal.Decimal" 型別的 NaN 值的雜湊值現在取決於物件
  的標識值 (identity)。以前即使 NaN 值彼此不相等，它們也總是被雜湊為
  "0"。由於在建立包含多個 NaN 的字典和集合時出現過多的雜湊衝突 (hash
  collision)，可能導致潛在的二次方執行環境行為 (quadratic runtime
  behavior)。（由 Raymond Hettinger 在 bpo-43475 中貢獻。）

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

* "SyntaxError" 例外現在具有 "end_lineno" 和 "end_offset" 屬性。如果未
  被決定，它們將會是 "None"。（由 Pablo Galindo 在 bpo-43914 中貢獻。
  ）


新模組
======

* None.


改進的模組
==========


asyncio
-------

新增缺少的 "connect_accepted_socket()" 方法。（由 Alex Grönholm 在
bpo-41332 中貢獻。）


argparse
--------

argparse 幫助中的誤導性用詞「可選引數 (optional arguments)」已被替換為
「選項 (options)」。某些依賴於精確輸出匹配的測試可能需要進行調整。（由
Raymond Hettinger 在 bpo-9694 中貢獻。）


array
-----

"array.array" 的 "index()" 方法現在具有可選的 *start* 和 *stop* 參數。
（由 Anders Lorentsen 和 Zackery Spytz 在 bpo-31956 中貢獻。）


asynchat, asyncore, smtpd
-------------------------

自 Python 3.6 起，這些模組在其文件中被標記為已棄用。引入時的
"DeprecationWarning" 現已新增到這三個模組中。


base64
------

新增 "base64.b32hexencode()" 和 "base64.b32hexdecode()" 以支援擴充十六
進位字母的 Base32 編碼 (Base32 Encoding with Extended Hex Alphabet)。


bdb
---

新增 "clearBreakpoints()" 來重置所有設定的斷點。（由 Irit Katriel 在
bpo-24160 中貢獻。）


bisect
------

新增向 "bisect" 模組 API 提供 *key* 函式的可能性。（由 Raymond
Hettinger 在 bpo-4356 中貢獻。）


codecs
------

新增 "codecs.unregister()" 函式來取消註冊 (unregister) 一個編解碼器的
搜索功能。 （Hai Shi在 bpo-41842 中貢獻。）


collections.abc
---------------

"collections.abc.Callable" 的參數化泛型 (parameterized generic) 的
"__args__" 現在與 "typing.Callable" 一致。"collections.abc.Callable"
泛型現在會將型別參數攤平，類似於 "typing.Callable" 目前的做法。這意味
著 "collections.abc.Callable[[int, str], str]" 將具有 "(int, str,
str)" 的 "__args__"；在以前這是 "([int, str], str)"。為了允許此更改，
現在可以對 "types.GenericAlias" 進行子類別化，並且在下標 (subscript)
"collections.abc.Callable" 型別時將回傳子類別。請注意，對於無效形式的
"collections.abc.Callable" 參數化可能會引發 "TypeError"，而在 Python
3.9 中該參數可能會無引發例外地傳遞。（由 Ken Jin 在 bpo-42195 中貢獻。
）


contextlib
----------

新增 "contextlib.aclosing()" 情境管理器以安全地關閉非同步產生器和表示
非同步釋放資源的物件。（由 Joongi Kim 和 John Belmonte 在 bpo-41229 中
貢獻。）

向 "contextlib.nullcontext()" 新增非同步情境管理器支援。（由 Tom
Gringauz 在 bpo-41543 中貢獻。）

新增 "AsyncContextDecorator"，用於支援將非同步情境管理器作為裝飾器使用
。


curses
------

ncurses 6.1 中新增的擴充顏色函式將由 "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" 函式庫提供的，那麼它們現在會在
curses 模組中公開。（由 Zackery Spytz 在 bpo-39273 中貢獻。）


dataclasses
-----------


__slots__
~~~~~~~~~

在 "dataclasses.dataclass()" 裝飾器中新增了 "slots" 參數。（由 Yurii
Karabas 在 bpo-42269 中貢獻）


僅限關鍵字欄位 (Keyword-only fields)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

dataclasses 現在支援在產生的 __init__ 方法中包含僅限關鍵字的欄位。有多
種方法可以指定僅限關鍵字欄位。

你可以說每個欄位都是關鍵字：

   from dataclasses import dataclass

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

"name" 和 "birthday" 都是產生的 __init__ 方法的僅限關鍵字參數。

你可以在每個欄位的基礎上指定僅限關鍵字：

   from dataclasses import dataclass, field

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

這裡只有 "birthday" 是僅限關鍵字。如果你在各個欄位上設定 "kw_only"，請
注意，由於僅限關鍵字欄位需要遵循非僅限關鍵字欄位，因此會有欄位重新排序
的相關規則。詳細資訊請參閱完整的 dataclasses 文件。

你還可以指定 KW_ONLY 標記後面的所有欄位均為僅限關鍵字欄位。這可能是最
常見的用法：

   from dataclasses import dataclass, KW_ONLY

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

這裡的 "z" 和 "t" 是僅限關鍵字參數，而 "x" 和 "y" 則不是。（由 Eric V.
Smith 在 bpo-43532 中貢獻。）


distutils
---------

整個 "distutils" 套件已被棄用，將在 Python 3.12 中刪除。它指定套件建置
的功能已經完全被第三方套件 "setuptools" 和 "packaging" 所取代，並且大
多數其他常用的 API 都可以在標準函式庫的其他地方被找到（例如 "platform"
、"shutil"、"subprocess" 或 "sysconfig"）。目前沒有將 "distutils" 遷移
任何其他地方的計畫，且使用其他功能的應用程式應該開始規劃如何取得程式碼
的私有副本。請參閱 **PEP 632** 的討論。

Python 3.8 中不推薦使用的 "bdist_wininst" 命令已被刪除。現在建議使用
"bdist_wheel" 命令來在 Windows 上發布二進位套件。（由 Victor Stinner
在 bpo-42802 中貢獻。）


doctest
-------

當模組未定義 "__loader__" 時，回退到 "__spec__.loader" 。（由 Brett
Cannon 在 bpo-42133 中貢獻。）


encodings
---------

"encodings.normalize_encoding()" 現在會忽略非 ASCII 字元。（Hai Shi 在
bpo-39337 中貢獻。）


enum
----

"Enum" "__repr__()" 現在會回傳 "enum_name.member_name" 、"__str__()"
現在會回傳 "member_name" 。可用作模組常數的標準函式庫列舉會有
"module_name.member_name" 的 "repr()"。（由 Ethan Furman 在 bpo-40066
中貢獻。）

新增 "enum.StrEnum"，為所有成員都是字串的列舉。（由 Ethan Furman 在
bpo-41816 中貢獻。）


fileinput
---------

在 "fileinput.input()" 和 "fileinput.FileInput" 中新增 *encoding* 和
*errors* 參數。（由 Inada Naoki 在 bpo-43712 中貢獻。）

當 *mode* 為 "r" 並且檔案有被壓縮時，"fileinput.hook_compressed()" 現
在會回傳 "TextIOWrapper" 物件（和未壓縮檔案一樣）。（由 Inada Naoki 在
bpo-5758 中貢獻。）


faulthandler
------------

"faulthandler" 模組現在可以檢測垃圾收集器 (garbage collector) 在收集期
間是否發生嚴重錯誤。（由 Victor Stinner 在 bpo-44466 中貢獻。）


gc
--

為 "gc.get_objects()"、"gc.get_referrers()" 和 "gc.get_referents()" 新
增稽核掛鉤 (audit hooks)。（由 Pablo Galindo 在 bpo-43439 中貢獻。）


glob
----

在 "glob()" 和 "iglob()" 中新增 *root_dir* 和 *dir_fd* 參數，允許指定
搜索的根目錄。（由 Serhiy Storchaka 在 bpo-38144 中貢獻。）


hashlib
-------

hashlib 模組需要 OpenSSL 1.1.1 或更高版本。（由 Christian Heimes 在
**PEP 644** 和 bpo-43669 中貢獻。）

hashlib 模組初步支援 OpenSSL 3.0.0。（由 Christian Heimes 在 bpo-38820
和其他問題中貢獻。）

純 Python 的 "pbkdf2_hmac()" 回退已被棄用。將來只有在有 OpenSSL 支援的
建置 Python 中才能夠使用 PBKDF2-HMAC。（由 Christian Heimes 在
bpo-43880 中貢獻。）


hmac
----

hmac 模組現在在內部使用 OpenSSL 的 HMAC 實作。 （由 Christian Heimes
在 bpo-40645 中貢獻。）


IDLE 和 idlelib
---------------

讓 IDLE 調用 "sys.excepthook()" （在沒有 "-n" 的情況下啟動時）。使用者
掛鉤 (user hooks) 在以前是被忽略的。（由 Ken Hilton 在 bpo-43008 中貢
獻。）

重新排列設定對話框。將 General 分頁拆分為 Windows 和 Shell/Ed 分頁。將
擴充 Help 選單的幫助來源移至 Extensions 分頁。為新選項騰出空間並縮短對
話框，而後者使對話框更好地適應較小的螢幕。（由 Terry Jan Reedy 在
bpo-40468 中貢獻。）將縮排空間設定從 Font 分頁移至新的 Windows 分頁。
（由 Mark Roseman 和 Terry Jan Reedy 在 bpo-33962 中貢獻。）

上述更改已向後移植到 3.9 維護版本。

新增 Shell 側邊欄。將主要提示字元 (">>>") 移至側邊欄。將輔助提示字元（
"..."）新增到側邊欄。點擊左鍵再拖動能夠選擇一行或多行文字，和編輯器列
號側邊欄操作一樣。選擇文字列後點擊右鍵會顯示帶有「一併複製提示字元
(copy with prompts)」的情境選單，這會將側邊欄中提示字元與所選文字並排
，此選項也會出現在文字的情境選單上。（由 Tal Einat 在 bpo-37903 中貢獻
。）

使用空格而不是製表符號 (tab) 來縮進交互式程式碼。這能夠使交互式程式碼
條目「看起來正確」。新增 shell 側邊欄的主要動機是實現這一點。（由
Terry Jan Reedy 在 bpo-37892 中貢獻。）

突顯 (highlight) 模式匹配陳述式中的新軟關鍵字 (soft keywords) "match"
、"case" 和 "_"。然而這種突顯並不完美，並且在某些罕見的情況下會出錯，
包括 "case" 模式中的一些 "_"。（由 Tal Einat 在 bpo-44010 中貢獻。）

3.10 維護版本中的新增功能。

將語法突顯 (syntax highlighting) 應用於 ".pyi" 檔案。（由 Alex Waygood
和 Terry Jan Reedy 在 bpo-45447 中貢獻。）

保存帶有輸入和輸出的 Shell 時，會包含提示字元。（由 Terry Jan Reedy 在
gh-95191 中貢獻。）


importlib.metadata
------------------

與 "importlib_metadata" 4.6 功能相同（歷史）。

importlib.metadata 入口點現在透過新的 "importlib.metadata.EntryPoints"
類別提供了以群組和名稱選擇入口點的更好體驗。有關棄用與用法的更多資訊，
請參閱文件中的相容性說明。

新增了 "importlib.metadata.packages_distributions()" 用於將頂階 Python
模組和套件解析出 "importlib.metadata.Distribution"。


inspect
-------

當模組未定義 "__loader__" 時，回退到 "__spec__.loader" 。（由 Brett
Cannon 在 bpo-42133 中貢獻。）

新增 "inspect.get_annotations()"，它可以安全地計算物件上定義的註釋。它
是存取各種型別物件註釋的怪作法 (quirks) 的變通解法 (work around)，並且
對其檢查的物件做出很少的假設。 "inspect.get_annotations()" 也可以正確
地取消字串化註釋 (stringized annotations)。
"inspect.get_annotations()" 現在被認為是存取任何 Python 物件上定義的註
釋字典的最佳實踐；有關使用註釋的最佳實踐的更多資訊，請參閱 Annotations
Best Practices。相關地，"inspect.signature()"、
"inspect.Signature.from_callable()" 和
"inspect.Signature.from_function()" 現在呼叫
"inspect.get_annotations()" 來檢索註釋。這意味著 "inspect.signature()"
和 "inspect.Signature.from_callable()" 現在也可以取消字串化註釋。（由
Larry Hastings 在 bpo-43817 中貢獻。）


itertools
---------

新增 "itertools.pairwise()"。（由 Raymond Hettinger 在 bpo-38200 中貢
獻。）


linecache
---------

當模組未定義 "__loader__" 時，回退到 "__spec__.loader" 。（由 Brett
Cannon 在 bpo-42133 中貢獻。）


os
--

為 VxWorks RTOS 新增 "os.cpu_count()" 支援。（由 Peixing Xin 在
bpo-41440 中貢獻。）

新增函式 "os.eventfd()" 和相關幫助程式來包裝 Linux 上的 "eventfd2" 系
統呼叫。 （由 Christian Heimes 在 bpo-41001 中貢獻。）

新增 "os.splice()" 以允許在兩個檔案描述器 (file descriptor) 之間移動資
料，而無需在核心地址空間 (kernel address space) 和使用者地址空間 (user
address space) 之間進行複製，其中檔案描述器之一必須是個 pipe。（由
Pablo Galindo 在 bpo-41625 中貢獻。）

Add "O_EVTONLY", "O_FSYNC", "O_SYMLINK" and "O_NOFOLLOW_ANY" for
macOS. (Contributed by Donghee Na in bpo-43106.)


os.path
-------

"os.path.realpath()" 現在接受一個 *strict* 僅限關鍵字引數。當設定為
"True" 時，如果路徑不存在或遇到符號鏈接循環 (symlink loop)，則會引發
"OSError"。（由 Barney Gale 在 bpo-43757 中貢獻。）


pathlib
-------

新增 "PurePath.parents" 對於切片的支援。 （由 Joshua Cannon 在
bpo-35498 中貢獻。）

向 "PurePath.parents" 新增負索引支援。（由 Yaroslav Pankovych 在
bpo-21041 中貢獻。）

新增替代 "link_to()" 的 "Path.hardlink_to" 方法。新方法與
"symlink_to()" 具有相同的引數順序。（由 Barney Gale 在 bpo-39950 中貢
獻。）

"pathlib.Path.stat()" 和 "chmod()" 現在接受 *follow_symlinks* 僅限關鍵
字引數，以與 "os" 模組中的相應函式保持一致。（由 Barney Gale 在
bpo-39906 中貢獻。）


platform
--------

新增 "platform.freedesktop_os_release()" 以從 freedesktop.org os-
release 標準檔案中檢索出作業系統標識。 （由 Christian Heimes 在
bpo-28468 中貢獻。）


pprint
------

"pprint.pprint()" 現在接受新的 "underscore_numbers" 關鍵字引數。（由
sblondon 在 bpo-42914 中貢獻。）

"pprint" 現在可以漂亮地印出 "dataclasses.dataclass" 實例。（由 Lewis
Gaul 在 bpo-43080 中貢獻。）


py_compile
----------

將 "--quiet" 選項新增到 "py_compile" 的命令列界面。（由 Gregory
Schevchenko 在 bpo-38731 中貢獻。）


pyclbr
------

Add an "end_lineno" attribute to the "Function" and "Class" objects in
the tree returned by "pyclbr.readmodule()" and
"pyclbr.readmodule_ex()".  It matches the existing (start) "lineno".
(Contributed by Aviral Srivastava in bpo-38307.)


shelve
------

The "shelve" module now uses "pickle.DEFAULT_PROTOCOL" by default
instead of "pickle" protocol "3" when creating shelves. (Contributed
by Zackery Spytz in bpo-34204.)


statistics
----------

新增 "covariance()"、Pearson "correlation()" 和簡單
"linear_regression()" 函式。（由 Tymoteusz Wołodźko 在 bpo-38490 中貢
獻。）


site
----

當模組未定義 "__loader__" 時，回退到 "__spec__.loader" 。（由 Brett
Cannon 在 bpo-42133 中貢獻。）


socket
------

"socket.timeout" 例外現在是 "TimeoutError" 的別名。（由 Christian
Heimes 在 bpo-42413 中貢獻。）

新增使用 "IPPROTO_MPTCP" 建立 MPTCP socket 的選項（由 Rui Cunha 在
bpo-43571 中貢獻。）

新增 "IP_RECVTOS" 選項以接收服務型別 (type of service, ToS) 或
DSCP/ECN 欄位（由 Georg Sauthoff 在 44077 中貢獻。）


ssl
---

ssl 模組需要 OpenSSL 1.1.1 或更高版本。（由 Christian Heimes 在 **PEP
644** 和 bpo-43669 中貢獻。）

The ssl module has preliminary support for OpenSSL 3.0.0 and new
option "OP_IGNORE_UNEXPECTED_EOF". (Contributed by Christian Heimes in
bpo-38820, bpo-43794, bpo-43788, bpo-43791, bpo-43799, bpo-43920,
bpo-43789, and bpo-43811.)

已棄用函式和使用已棄用常數現在會導致 "DeprecationWarning"。
"ssl.SSLContext.options" 預設設定有 "OP_NO_SSLv2" 和 "OP_NO_SSLv3"，因
此無法再次發出設定該旗標的警告。棄用部分包含已棄用功能的列表。（由
Christian Heimes 在 bpo-43880 中貢獻。）

ssl 模組現在具有更安全的預設設定。預設情況下禁用沒有前向保密或 SHA-1
MAC 的密碼。安全級別 2 禁止安全性低於 112 位元的弱 RSA、DH 和 ECC 密鑰
。 "SSLContext" 預設為最低協議版本 TLS 1.2。設定基於 Hynek Schlawack
的研究。 （由 Christian Heimes 在 bpo-43998 中貢獻。）

不再正式支援已棄用的協議 SSL 3.0、TLS 1.0 和 TLS 1.1。 Python 不會主動
阻止它們。然而，OpenSSL 建置選項、發行版配置、發行商補丁和密碼套件可能
會阻止交握的成功。

向 "ssl.get_server_certificate()" 函式新增 *timeout* 參數。（由
Zackery Spytz 在 bpo-31870 中貢獻。）

ssl 模組使用堆疊類型 (heap-types) 和多階段初始化 (multi-phase
initialization)。（由 Christian Heimes 在 bpo-42333 中貢獻。）

A new verify flag "VERIFY_X509_PARTIAL_CHAIN" has been added.
(Contributed by l0x in 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"，其中包含標準函式庫模組的名稱列表。 （
由 Victor Stinner 在 bpo-42955 中貢獻。）


_thread
-------

"_thread.interrupt_main()" now takes an optional signal number to
simulate (the default is still "signal.SIGINT"). (Contributed by
Antoine Pitrou in bpo-43356.)


threading
---------

新增 "threading.gettrace()" 和 "threading.getprofile()" 分別取得
"threading.settrace()" 和 "threading.setprofile()" 設定的函式。（由
Mario Corchero 在 bpo-42251 中貢獻。）

新增 "threading.__excepthook__" 以允許取得 "threading.excepthook()" 的
原始值，以防它被設定為損壞或不同的值。（由 Mario Corchero 在 bpo-42308
中貢獻。）


traceback
---------

"format_exception()"、"format_exception_only()" 和 "print_exception()"
函式現在可以將例外物件作為僅限位置引數。（由 Zackery Spytz 和 Matthias
Bussonnier 在 bpo-26389 中貢獻。）


types
-----

重新引入 "types.EllipsisType"、"types.NoneType" 和
"types.NotImplementedType" 類別，提供一組易於型別檢查器直譯的新型別。
（由 Bas van Beek 在 bpo-41810 中貢獻。）


typing
------

有關重大更改，請參閱與型別提示相關的新功能。

"typing.Literal" 的行為已更改為符合 **PEP 586** 並匹配 PEP 中指定的靜
態型別檢查器的行為。

1. "Literal" 現在可以刪除重複參數。

2. "Literal" 物件之間的相等性比較現在與順序無關。

3. 現在型別的比較會優先於 "Literal" 的比較。例如，"Literal[0] ==
   Literal[False]" 先前之求值為 "True"，但現在它是 "False"。為了支援此
   更改，內部使用的型別快取現在支援了型別的辨認。

4. 如果 "Literal" 物件的任ㄧ參數不是*可雜湊的*，那麼它們現在將在相等性
   比較期間引發 "TypeError" 例外。請注意，使用不可雜湊的參數宣告
   "Literal" 不會引發錯誤：

      >>> 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()" 來自我審查 (introspect) 註釋是否為
"typing.TypedDict"。（由 Patrick Reader 在 bpo-41792 中貢獻。）

僅宣告了資料變數的 "typing.Protocol" 子類別現在在使用 "isinstance" 檢
查時會引發 "TypeError" ，除非它們用 "runtime_checkable()" 裝飾。此前，
這些檢查都是悄無聲息地通過的。如果使用者需要執行環境協議 (runtime
protocol)，則應該使用 "runtime_checkable()" 裝飾器來裝飾其子類別。（由
Yurii Karabas 在 bpo-38908 中貢獻。）

從 "typing.io" 和 "typing.re" 子模組引入現在將發出
"DeprecationWarning"。這些子模組自 Python 3.8 起已被棄用，並將在未來版
本的 Python 中刪除。屬於這些子模組的任何內容都應該直接從 "typing" 引入
。 （由 Sebastian Rittau 在 bpo-38291 中貢獻。）


unittest
--------

新增方法 "assertNoLogs()" 以補足現有的 "assertLogs()"。（由 Kit Yan
Choi 在 bpo-39385 中貢獻。）


urllib.parse
------------

Python 3.10 之前的 Python 版本允許在 "urllib.parse.parse_qs()" 和
"urllib.parse.parse_qsl()" 中使用 ";" 和 "&" 作為查詢參數 (query
parameter) 的分隔符號。出於安全考慮，並且為了符合更新的 W3C 建議，已將
其更改為僅允許單個分隔符號鍵，預設為 "&"。此更改還會影響 "cgi.parse()"
和 "cgi.parse_multipart()"，因為它們在內部使用受影響的函式。有關更多詳
細資訊，請參閱各自的文件。（由 Adam Goldschmidt、Senthil Kumaran 和
Ken Jin 在 bpo-42967 中貢獻。）

The presence of newline or tab characters in parts of a URL allows for
some forms of attacks. Following the WHATWG specification that updates
**RFC 3986**, ASCII newline "\n", "\r" and tab "\t" characters are
stripped from the URL by the parser in "urllib.parse" preventing such
attacks. The removal characters are controlled by a new module level
variable "urllib.parse._UNSAFE_URL_BYTES_TO_REMOVE". (See gh-88048)


xml
---

新增 "LexicalHandler" 類別到 "xml.sax.handler" 模組。（由 Jonathan
Gossage 和 Zackery Spytz 在 bpo-35018 中貢獻。）


zipimport
---------

新增與 **PEP 451** 相關的方法："find_spec()"、
"zipimport.zipimporter.create_module()" 和
"zipimport.zipimporter.exec_module()"。（由 Brett Cannon 在 bpo-42131
中貢獻。）

新增 "invalidate_caches()" 方法。（由 Desmond Cheong 在 bpo-14678 中貢
獻。）


最佳化
======

* 建構函式 "str()"、"bytes()" 和 "bytearray()" 現在更快了（對於小型物
  件大約快了 30--40%）。（由 Serhiy Storchaka 在 bpo-41334 中貢獻。）

* "runpy" 模組現在引入更少的模組。"python3 -m module-name" 指令啟動時
  間平均快了 1.4 倍。在 Linux 上，"python3 -I -m module-name" 在
  Python 3.9 上引入 69 個模組，而在 Python 3.10 上僅引入 51 個模組
  (-18)。（由 Victor Stinner 在 bpo-41006 和 bpo-41718 中貢獻。）

* "LOAD_ATTR" 指令現在使用新的「操作碼快取 (per opcode cache)」機制。
  現在一般屬性的速度提高了約 36%，槽位 (slot) 的速度提高了 44%。（由
  Pablo Galindo 和 Yury Selivanov 在 bpo-42093 中以及 Guido van Rossum
  在 bpo-42927 中貢獻，基於最初在 PyPy 和 MicroPython 中實作的想法。）

* 當使用 "--enable-optimizations" 建置 Python 時，現在 "-fno-semantic-
  interposition" 被新增到編譯和鏈接列 (link line) 中。這使得使用 "--
  enable-shared" 和 "gcc" 建立的 Python 直譯器的建置速度提高了 30%。請
  參閱本文 以了解詳情。（由 Victor Stinner 和 Pablo Galindo 在
  bpo-38980 中貢獻。）

* 對 "bz2" / "lzma" / "zlib" 模組使用新的輸出緩衝區管理程式碼，並將
  ".readall()" 函式新增到 "_compression.DecompressReader" 類別。 bz2
  解壓縮速度提高了 1.09x ~ 1.17x，lzma 解壓縮速度提高了 1.20x ~ 1.32x
  ，"GzipFile.read(-1)" 速度提高了 1.11x ~ 1.18x。（由 Ma Lin 於
  bpo-41486 貢獻、由 Gregory P. Smith 審閱）

* 使用字串化註釋時，建立函式時不再建立函式的註釋字典。取而代之的是它們
  被存儲為字串元組，且函式物件會根據需求才將其延遲轉換 (lazily
  convert) 為註釋字典。此最佳化將定義帶有註釋的函式所需的 CPU 時間減少
  了一半。（由 Yurii Karabas 和 Inada Naoki 在 bpo-42202 中貢獻。）

* 像是 "str1 in str2" 和 "str2.find(str1)" 之類的子字串搜索函式現在有
  時會使用 Crochemore & Perrin 的「雙向」字串搜索演算法來避免作用於長
  字串上時發生二次方行為 (quadratic behavior)。（由 Dennis Sweeney 在
  bpo-41972 中貢獻）

* 向 "_PyType_Lookup()" 新增微最佳化以提高快取命中的常見情況下的型別屬
  性快取查找性能。這使得直譯器平均速度提高了 1.04 倍。（由 Dino
  Viehland 在 bpo-43452 中貢獻。）

* The following built-in functions now support the faster **PEP 590**
  vectorcall calling convention: "map()", "filter()", "reversed()",
  "bool()" and "float()". (Contributed by Donghee Na and Jeroen
  Demeyer in bpo-43575, bpo-43287, bpo-41922, bpo-41873 and
  bpo-41870.)

* 通過刪除內部 "RLock"，"BZ2File" 的性能得到了改進。這使得 "BZ2File"
  在面對多個同時的讀取器或寫入器時執行緒不安全，就像 "gzip" 和 "lzma"
  中的等效類別一樣。（由 Inada Naoki 在 bpo-43785 中貢獻。）


已棄用
======

* 目前 Python 接受緊跟關鍵字的數字字面值 (numeric literals)，例如 "0in
  x"、"1or x"、"0if 1else 2"。它允許了令人困惑和不明確的運算式，例如
  "[0x1for x in y]" （可以直譯為 "[0x1 for x in y]" 或 "[0x1f or x in
  y]" ）。從此版本開始，如果數字字面值後緊跟關鍵字 "and"、"else"、
  "for"、"if"、"in"、"is" 與 "or" 其中之一，則會引發棄用警告。在未來的
  版本中，它將被變更為語法警告，最後成為為語法錯誤。（由 Serhiy
  Storchaka 在 bpo-43833 中貢獻。）

* 從這個版本開始，我們將齊心協力開始清理為相容 Python 2.7 而保留的舊引
  入語義。具體來說， "find_loader()"/"find_module()" （被
  "find_spec()" 取代）、 "load_module()" （被 "exec_module()" 取代）、
  "module_repr()" （引入系統負責處理你）、"__package__" 屬性（由
  "__spec__.parent" 取代）、 "__loader__" 屬性（由 "__spec__.loader"
  取代）和 "__cached__" 屬性（由 "__spec__.cached" 取代）將慢慢被刪除
  （以及 "importlib" 中的其他類別和方法）。將酌情引發 "ImportWarning"
  和/或 "DeprecationWarning" 以幫助識別在此轉換期間需要更新的程式碼。

* 整個 "distutils" 命名空間已棄用，將在 Python 3.12 中刪除。請參閱模組
  更改 以獲取更多資訊。

* "random.randrange()" 的非整數引數已棄用。"ValueError" 已被棄用，取而
  代之的是 "TypeError"。（由 Serhiy Storchaka 和 Raymond Hettinger 在
  bpo-37319 中貢獻。）

* "importlib" 的各種 "load_module()" 方法自 Python 3.6 起已被記錄為已
  棄用，但現在也會觸發 "DeprecationWarning"。請改用 "exec_module()"。
  （由 Brett Cannon 在 bpo-26131 中貢獻。）

* "zimport.zipimporter.load_module()" 已被棄用，請用 "exec_module()"。
  （由 Brett Cannon 在 bpo-26131 中貢獻。）

* 引入系統使用 "load_module()" 現在會觸發 "ImportWarning"，因為
  "exec_module()" 是當前首選。（由 Brett Cannon 在 bpo-26131 中貢獻。
  ）

* 引入系統使用 "importlib.abc.MetaPathFinder.find_module()" 和
  "importlib.abc.PathEntryFinder.find_module()" 現在會觸發
  "ImportWarning" 作為 "importlib.abc.MetaPathFinder.find_spec()" 和
  "importlib.abc.PathEntryFinder.find_spec()" 分別是首選。你可以使用
  "importlib.util.spec_from_loader()" 來幫助移植。（由 Brett Cannon 在
  bpo-42134 中貢獻。）

* 引入系統使用 "importlib.abc.PathEntryFinder.find_loader()" 現在會觸
  發 "ImportWarning"，因為 "importlib.abc.PathEntryFinder.find_spec()"
  是首選。你可以使用 "importlib.util.spec_from_loader()" 來幫助移植。
  （由 Brett Cannon 在 bpo-43672 中貢獻。）

* "importlib.abc.MetaPathFinder.find_module()" 的各種實作（
  "importlib.machinery.BuiltinImporter.find_module()"、
  "importlib.machinery.FrozenImporter.find_module()"、
  "importlib.machinery.WindowsRegistryFinder.find_module()"、
  "importlib.machinery.PathFinder.find_module()"、
  "importlib.abc.MetaPathFinder.find_module()" )、
  "importlib.abc.PathEntryFinder.find_module()"
  ("importlib.machinery.FileFinder.find_module()" ) 和
  "importlib.abc.PathEntryFinder.find_loader()"
  ("importlib.machinery.FileFinder.find_loader()" ) 現在引發
  "DeprecationWarning" 並計劃在 Python 3.12 中刪除（之前它們已在
  Python 3.4 中被記錄為已棄用）。（由 Brett Cannon 在 bpo-42135 中貢獻
  。）

* "importlib.abc.Finder" 已被棄用（包括其唯一方法 "find_module()"）。
  "importlib.abc.MetaPathFinder" 和 "importlib.abc.PathEntryFinder" 都
  不再從該類別繼承。使用者應該根據需求來選擇其一以繼承。 （由 Brett
  Cannon 在 bpo-42135 中貢獻。）

* 棄用 "imp"、"importlib.find_loader()"、
  "importlib.util.set_package_wrapper()"、
  "importlib.util.set_loader_wrapper()"、
  "importlib.util.module_for_loader()"、"pkgutil.ImpImporter" 和
  "pkgutil.ImpLoader" 均已更新，將於 Python 3.12 列為預定的刪除版本（
  它們開始在過去版本的 Python 中引發 "DeprecationWarning"） 。（由
  Brett Cannon 在 bpo-43720 中貢獻。）

* 引入系統現在在模組上使用 "__spec__" 屬性，然後才會回退使用
  "module_repr()" 作為模組的 "__repr__()" 方法。計劃在 Python 3.12 中
  刪除 "module_repr()" 的使用。（由 Brett Cannon 在 bpo-42137 中貢獻。
  ）

* "importlib.abc.Loader.module_repr()"、
  "importlib.machinery.FrozenLoader.module_repr()" 和
  "importlib.machinery.BuiltinLoader.module_repr()" 已棄用並計劃在
  Python 3.12 中刪除。（由 Brett Cannon 在 bpo-42136 中貢獻。）

* 自 Python 3.3 起，"sqlite3.OptimizedUnicode" 就沒有文件記錄並且已過
  時，當時它被用作 "str" 的別名。它現已被棄用，並計劃在 Python 3.12 中
  刪除。（由 Erlend E. Aasland 在 bpo-42264 中貢獻。）

* 未記錄於說明文件的內建函式 "sqlite3.enable_shared_cache" 現已棄用，
  計劃在 Python 3.12 中刪除。SQLite3 文件強烈建議不去使用它。有關更多
  詳細資訊，請參閱 SQLite3 文件。如果必須使用共享快取，請使用
  "cache=shared" 查詢參數以 URI 模式打開資料庫。（由 Erlend E. Aasland
  在 bpo-24464 中貢獻。）

* 以下 "threading" 方法現已棄用：

  * "threading.currentThread" => "threading.current_thread()"

  * "threading.activeCount" => "threading.active_count()"

  * "threading.Condition.notifyAll" =>
    "threading.Condition.notify_all()"

  * "threading.Event.isSet" => "threading.Event.is_set()"

  * "threading.Thread.setName" => "threading.Thread.name"

  * "threading.thread.getName" => "threading.Thread.name"

  * "threading.Thread.isDaemon" => "threading.Thread.daemon"

  * "threading.Thread.setDaemon" => "threading.Thread.daemon"

  （由 Jelle Zijlstra 在 gh-87889 中貢獻。）

* "pathlib.Path.link_to()" 已棄用並計劃在 Python 3.12 中刪除。請改用
  "pathlib.Path.hardlink_to()"。（由 Barney Gale 在 bpo-39950 中貢獻。
  ）

* "cgi.log()" 已棄用並計劃在 Python 3.12 中刪除。（由 Inada Naoki 在
  bpo-41139 中貢獻。）

* 自 Python 3.6、Python 3.7 或 OpenSSL 1.1.0 起，以下 "ssl" 功能已被棄
  用，並將在 3.11 中刪除：

  * "OP_NO_SSLv2"、"OP_NO_SSLv3"、"OP_NO_TLSv1"、"OP_NO_TLSv1_1"、
    "OP_NO_TLSv1_2"、和 "OP_NO_TLSv1_3" 已被替換為
    "sslSSLContext.minimum_version" 和 "sslSSLContext.maximum_version"
    。

  * "PROTOCOL_SSLv2", "PROTOCOL_SSLv3", "PROTOCOL_SSLv23",
    "PROTOCOL_TLSv1", "PROTOCOL_TLSv1_1", "PROTOCOL_TLSv1_2", and
    "PROTOCOL_TLS" are deprecated in favor of "PROTOCOL_TLS_CLIENT"
    and "PROTOCOL_TLS_SERVER"

  * "wrap_socket()" 被替換為 "ssl.SSLContext.wrap_socket()"

  * "match_hostname()"

  * "RAND_pseudo_bytes()", "RAND_egd()"

  * NPN 功能如 "ssl.SSLSocket.selected_npn_protocol()" 和
    "ssl.SSLContext.set_npn_protocols()" 已被 ALPN 取代。

* 執行緒除錯（"PYTHONTHREADDEBUG" 環境變數）在 Python 3.10 中已棄用，
  並將在 Python 3.12 中刪除。此功能需要一個 Python 的除錯用建置版本。
  （由 Victor Stinner 在 bpo-44584 中貢獻。）

* 從 "typing.io" 和 "typing.re" 子模組引入現在將發出
  "DeprecationWarning"。這些子模組將在 Python 的未來版本中刪除。屬於這
  些子模組的任何內容都應該直接從 "typing" 引入。（由 Sebastian Rittau
  在 bpo-38291 中貢獻。）


已刪除
======

* 刪除了 "complex" 類別的特殊方法 "__int__"、"__float__"、
  "__floordiv__"、"__mod__"、"__divmod__"、"__rfloordiv__"、"__rmod__"
  和 "__rdivmod__" 。它們都會引發 "TypeError"。（由 Serhiy Storchaka
  在 bpo-41974 中貢獻。）

* "_markupbase" 模組中私有、未於文件記錄的 "ParserBase.error()" 方法已
  被刪除。"html.parser.HTMLParser" 是 "ParserBase" 的唯一子類別，它的
  "error()" 實作已在 Python 3.5 中刪除。（由 Berker Peksag 在
  bpo-31844 中貢獻。）

* 刪除了 "unicodedata.ucnhash_CAPI" 屬性，該屬性是內部 PyCapsule 物件
  。相關的私有 "_PyUnicode_Name_CAPI" 結構已移至內部 C API。（由
  Victor Stinner 在 bpo-42157 中貢獻。）

* 刪除了由於切換到新的 PEG 剖析器而在 3.9 中被棄用的 "parser" 模組。僅
  由舊剖析器使用的所有 C 原始碼和標頭檔也已被刪除，包括 "node.h"、
  "parser.h"、"graminit.h" 和 "grammar.h"。

* 刪除了公開 C API 函式 "PyParser_SimpleParseStringFlags"、
  "PyParser_SimpleParseStringFlagsFilename"、
  "PyParser_SimpleParseFileFlags" 和 "PyNode_Compile"，這些函式由於切
  換到新的 PEG 剖析器而在 3.9 中被棄用。

* Removed the "formatter" module, which was deprecated in Python 3.4.
  It is somewhat obsolete, little used, and not tested. It was
  originally scheduled to be removed in Python 3.6, but such removals
  were delayed until after Python 2.7 EOL. Existing users should copy
  whatever classes they use into their code. (Contributed by Donghee
  Na and Terry J. Reedy in bpo-42299.)

* Removed the "PyModule_GetWarningsModule()" function that was useless
  now due to the "_warnings" module was converted to a builtin module
  in 2.6. (Contributed by Hai Shi in bpo-42599.)

* 從 "collections" 模組中刪除已棄用的、對 Collections Abstract Base
  Classes 的別名。（由 Victor Stinner 在 bpo-37324 中貢獻。）

* 在 Python 3.8 中棄用後，"loop" 參數已從大多數 "asyncio" 的高階 API
  中刪除。這一變化的背後動機是多方面的：

  1. 這簡化了高階 API。

  2. 自 Python 3.7 以來，高階 API 中的函式一直隱式獲取當前執行緒正在運
     行的事件循環。在大多數正常用例中，不需要將事件循環傳遞給 API。

  3. 事件循環的傳遞很容易出錯，尤其是在處理在不同執行緒中運行的循環時
     。

  請注意，低階 API 仍會接受 "loop"。有關如何替換現有程式碼的範例，請參
  閱 Python API 的變化。

  （由 Yurii Karabas、Andrew Svetlov、Yury Selivanov 和 Kyle Stanley
  在 bpo-42392 中貢獻。）


移植到 Python 3.10
==================

本節列出了前面描述的更改以及可能需要更改程式碼的其他錯誤修復。


Python 語法的變化
-----------------

* 如果數字字面值後面緊跟關鍵字（如 "0in x"），在以前是有效的語法，但現
  在在編譯時會發出棄用警告。在未來的版本中，它將更改為語法警告，最後更
  改為語法錯誤。要消除警告並使程式碼與未來版本相容，只需在數字字面值和
  以下關鍵字之間新增一個空格即可。（由 Serhiy Storchaka 在 bpo-43833
  中貢獻。）


Python API 的變化
-----------------

* "format_exception()"、"format_exception_only()" 和 "traceback" 模組
  中的 "print_exception()" 函式的 *etype* 參數已重命名為 *exc*。（由
  Zackery Spytz 和 Matthias Bussonnier 在 bpo-26389 中貢獻。）

* "atexit"：在 Python 退出時，如果一個使用 "atexit.register()" 註冊的
  回呼 (callback) 失敗，該例外現在會被記錄下來。在以前只記錄一些例外，
  並且最後一個例外總是被默默地忽略。（由 Victor Stinner 在 bpo-42639
  中貢獻。）

* "collections.abc.Callable" 泛型現在會攤平型別參數，類似於
  "typing.Callable" 目前的做法。這意味著
  "collections.abc.Callable[[int, str], str]" 將具有 "(int, str, str)"
  的 "__args__"；以前這是 "([int, str], str)"。透過
  "typing.get_args()" 或 "__args__" 存取參數的程式碼需要考慮此變更。此
  外，對於無效形式的參數化 "collections.abc.Callable"，可能會引發
  "TypeError"，而在 Python 3.9 中，該參數可能已被默默地傳遞。（由 Ken
  Jin 在 bpo-42195 中貢獻。）

* 如果給定參數不適合 16 位元無符號整數 (16-bit unsigned integer)，
  "socket.htons()" 和 "socket.ntohs()" 現在會引發 "OverflowError" 而不
  是 "DeprecationWarning"。（由 Erlend E. Aasland 在 bpo-42393 中貢獻
  。）

* 在 Python 3.8 中棄用後，"loop" 參數已從大多數 "asyncio" 的高階 API
  中刪除。

  目前如下所示的協程：

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

  應替換為：

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

  如果 "foo()" 被專門設計為 *不* 在當前執行緒的事件循環中運行（例如在
  另一個執行緒的事件循環中運行），請考慮改用
  "asyncio.run_coroutine_threadsafe()"。

  （由 Yurii Karabas、Andrew Svetlov、Yury Selivanov 和 Kyle Stanley
  在 bpo-42392 中貢獻。）

* 如果 *globals* 字典沒有 ""__builtins__"" 鍵，則 "types.FunctionType"
  建構函式現在會繼承當前的內建物件，而不是使用 "{"None": None}"：相同
  行為如 "eval()" 和 "exec()" 函式。在 Python 中使用 "def
  function(...): ..." 定義函式不受影響，全域變數不能用此語法覆蓋：它也
  繼承當前的內建物件。 （由 Victor Stinner 在 bpo-42990 中貢獻。）


C API 中的改動
--------------

* 由於切換到新的 PEG 剖析器，C API 函式
  "PyParser_SimpleParseStringFlags"、
  "PyParser_SimpleParseStringFlagsFilename"、
  "PyParser_SimpleParseFileFlags"、"PyNode_Compile" 和被這些函式使用的
  型別 "struct _node" 被刪除。

  現在應該將源程式碼直接（例如透過 "Py_CompileString()"）編譯為程式碼
  物件。然後可以（例如透過 "PyEval_EvalCode()"）為產生的程式碼物件求值
  (evaluated)。

  具體來說：

  * 後跟有 "PyNode_Compile" 呼叫的 "PyParser_SimpleParseStringFlags"
    呼叫，可以替換為呼叫 "Py_CompileString()"。

  * 沒有 "PyParser_SimpleParseFileFlags" 的直接替代品。要從 "FILE *"
    引數編譯程式碼，你需要用 C 讀取檔案並將結果緩衝區傳遞給
    "Py_CompileString()"。

  * 要編譯給定 "char *" 檔案名稱的檔案，請顯式打開該檔案，讀取它並編譯
    結果。一種方法是使用 "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" 指令現在接受字典或字串元組作為函式的註釋。（由 Yurii
  Karabas 和 Inada Naoki 在 bpo-42202 中貢獻。）


建置變更
========

* **PEP 644**：Python 現在需要 OpenSSL 1.1.1 或更高版本。不再支援
  OpenSSL 1.0.2。（由 Christian Heimes 在 bpo-43669 中貢獻。）

* 現在需要 C99 函式 "snprintf()" 和 "vsnprintf()" 來建置 Python。 （由
  Victor Stinner 在 bpo-36020 中貢獻。）

* "sqlite3" 需要 SQLite 3.7.15 或更新版本。（由 Sergey Fedoseev 和
  Erlend E. Aasland 在 bpo-40744 和 bpo-40810 中貢獻。）

* "atexit" 模組現在必須都被建置為內建模組。（由 Victor Stinner 在
  bpo-42639 中貢獻。）

* 將 "--disable-test-modules" 選項新增到 "configure" 腳本中：不建置也
  不安裝測試模組。（由 Xavier de Gaye、Thomas Petazzoni 和 Peixing Xin
  在 bpo-27640 中貢獻。）

* 將 "--with-wheel-pkg-dir=PATH 選項" 新增到 "./configure" 腳本中。如
  果有指定，"ensurepip" 模組會在此目錄中查找 "setuptools" 和 "pip"
  wheel 套件：如果兩者都存在，則使用這些 wheel 套件而不是 ensurepip 捆
  綁的 wheel 套件。

  一些 Linux 發行版的打包策略建議不要一併包入依賴項目。例如，Fedora 在
  "/usr/share/python-wheels/" 目錄中安裝 wheel 套件，並且不安裝
  "ensurepip._bundled" 套件。

  （由 Victor Stinner 在 bpo-42856 中貢獻。）

* 新增 "configure --without-static-libpython 選項" 以不建置
  "libpythonMAJOR.MINOR.a" 靜態函式庫且不安裝 "python.o" 目標檔案。

  （由 Victor Stinner 在 bpo-43103 中貢獻。）

* 如果可用，"configure" 腳本現在使用 "pkg-config" 工具程式 (utility)
  來檢測 Tcl/Tk 標頭檔和函式庫的位置。和以前一樣，可以使用 "--with-
  tcltk-includes" 和 "--with-tcltk-libs" 配置選項顯式指定這些位置。（
  由 Manolis Stamatogiannakis 在 bpo-42603 中貢獻。）

* 將 "--with-openssl-rpath" 選項新增到 "configure" 腳本中。該選項簡化
  了使用自定義 OpenSSL 安裝建置 Python 的過程，例如 "./configure
  --with-openssl=/path/to/openssl --with-openssl-rpath=auto"。（由
  Christian Heimes 在 bpo-43466 中貢獻。）


C API 變更
==========


PEP 652：維護穩定 ABI
---------------------

用於擴充模組或嵌入 Python 的穩定 ABI（應用程式二進位介面）現已明確定義
。 C API 穩定性 描述了 C API 和 ABI 穩定性保證以及使用穩定 ABI 的最佳
實踐。

（由 Petr Viktorin 在 **PEP 652** 和 bpo-43795 中貢獻。）


新功能
------

* "PyNumber_Index()" 的結果現在都具有精確的 "int" 型別。在以前，結果可
  能是 "int" 子類別的實例。（由 Serhiy Storchaka 在 bpo-40792 中貢獻。
  ）

* 將新的 "orig_argv" 成員新增到 "PyConfig" 結構：傳遞給 Python 可執行
  檔案的原始命令列參數列表。（由 Victor Stinner 在 bpo-23427 中貢獻。
  ）

* 新增了 "PyDateTime_DATE_GET_TZINFO()" 和
  "PyDateTime_TIME_GET_TZINFO()" 巨集，用於存取 "datetime.datetime" 和
  "datetime.time" 物件的 "tzinfo" 屬性。（由 Zackery Spytz 在
  bpo-30155 中貢獻。）

* 新增 "PyCodec_Unregister()" 函式來取消註冊編解碼器搜索函式。（由 Hai
  Shi 在 bpo-41842 中貢獻。）

* 新增了 "PyIter_Send()" 函式，以允許將值發送到疊代器中，而不會引發
  "StopIteration" 例外。（由 Vladimir Matveev 在 bpo-41756 中貢獻。）

* 將 "PyUnicode_AsUTF8AndSize()" 新增到受限 C API (limited C API) 中。
  （由 Alex Gaynor 在 bpo-41784 中貢獻。）

* 新增 "PyModule_AddObjectRef()" 函式：類似於 "PyModule_AddObject()"
  但成功時不竊取對值的參照。（由 Victor Stinner 在 bpo-1635741 中貢獻
  。）

* 新增 "Py_NewRef()" 和 "Py_XNewRef()" 函式來增加物件的參照計數並回傳
  物件。 （由 Victor Stinner 在 bpo-42262 中貢獻。）

* "PyType_FromSpecWithBases()" 和 "PyType_FromModuleAndSpec()" 函式現
  在接受單個類別作為 *bases* 引數。（由 Serhiy Storchaka 在 bpo-42423
  中貢獻。）

* "PyType_FromModuleAndSpec()" 函式現在接受 NULL "tp_doc" 槽位。（由
  Hai Shi在 bpo-41832 中貢獻。）

* "PyType_GetSlot()" 函式可以接受靜態型別 (static type)。（由 Hai Shi
  和 Petr Viktorin 在 bpo-41073 中貢獻。）

* 向 C-API 新增 "PySet_CheckExact()" 函式，以檢查物件是否是 "set" 的實
  例而不是子型別的實例。（由 Pablo Galindo 在 bpo-43277 中貢獻。）

* 新增 "PyErr_SetInterruptEx()"，它允許傳遞信號編號來進行模擬。 （由
  Antoine Pitrou 在 bpo-43356 中貢獻。）

* 如 Python 是在除錯模式 (debug mode) 下建置的（如果有定義 "Py_DEBUG"
  巨集），現在會支援受限 C API。在受限 C API 中，如果 Python 是在除錯
  模式下建置的，並且 "Py_LIMITED_API" 巨集的目標是 Python 3.10 或更新
  版本，"Py_INCREF()" 和 "Py_DECREF()" 函式現在的實作是不透明函式呼叫
  ，而不是直接存取 "PyObject.ob_refcnt" 成員。在除錯模式下支援受限 C
  API 成為可能，因為自 Python 3.8 以來，"PyObject" 結構在發布和除錯模
  式下是相同的（請參閱:issue:*36465*）。

  "--with-trace-refs" 特殊建置（"Py_TRACE_REFS" 巨集）仍不支援受限 C
  API。（由 Victor Stinner 在 bpo-43688 中貢獻。）

* 新增 "Py_Is(x, y)" 函式來測試 *x* 物件是否為 *y* 物件，與 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 程式碼啟
  用、停用和查詢垃圾收集器的狀態，而無需引入 "gc" 模組。

* Add a new "Py_TPFLAGS_DISALLOW_INSTANTIATION" type flag to disallow
  creating type instances. (Contributed by Victor Stinner in
  bpo-43916.)

* Add a new "Py_TPFLAGS_IMMUTABLETYPE" type flag for creating
  immutable type objects: type attributes cannot be set nor deleted.
  (Contributed by Victor Stinner and Erlend E. Aasland in bpo-43908.)


移植到 Python 3.10
------------------

* 現在必須定義 "PY_SSIZE_T_CLEAN" 巨集以使用 "PyArg_ParseTuple()" 和
  "Py_BuildValue()" 格式，這些格式使用 "#": "es#", "et#"、"s#"、"u#"、
  "y#"、"z#"、"U#" 和 "Z#"。請參閱 剖析引數與建置數值 和 **PEP 353**。
  （由 Victor Stinner 在 bpo-40943 中貢獻。）

* 由於 "Py_REFCNT()" 更改為行內靜態函式 (inline static function)，因此
  "Py_REFCNT(obj) = new_refcnt" 必須替換為 "Py_SET_REFCNT(obj,
  new_refcnt)" ：參見 "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 中貢獻。）

* 由於過去的種種原因，過去在不持有 *GIL* 的情況下呼叫
  "PyDict_GetItem()" 是被允許的。目前已被禁止。（由 Victor Stinner 在
  bpo-40839 中貢獻。）

* "PyUnicode_FromUnicode(NULL, size)" 和
  "PyUnicode_FromStringAndSize(NULL, size)" 現在會引發
  "DeprecationWarning"。請改用 "PyUnicode_New()" 來分配沒有初始資料的
  Unicode 物件。（由 Inada Naoki 在 bpo-36346 中貢獻。）

* PyCapsule API "unicodedata.ucnhash_CAPI" 的私有
  "_PyUnicode_Name_CAPI" 結構已移至內部 C API。（由 Victor Stinner 在
  bpo-42157 中貢獻。）

* 如果在 "Py_Initialize()" 之前（Python 初始化之前）被呼叫，
  "Py_GetPath()"、"Py_GetPrefix()"、"Py_GetExecPrefix()"、
  "Py_GetProgramFullPath()"、"Py_GetPythonHome()" 和
  "Py_GetProgramName()" 現在會回傳 "NULL"。使用新的 Python
  Initialization Configuration API 來獲取 Python Path Configuration。
  （由 Victor Stinner 在 bpo-42260 中貢獻。）

* "PyList_SET_ITEM()"、"PyTuple_SET_ITEM()" 和 "PyCell_SET()" 巨集不能
  再用作左值 (l-value) 或右值 (r-value)。例如，"x = PyList_SET_ITEM(a,
  b, c)" 和 "PyList_SET_ITEM(a, b, c) = x" 現在會失敗並出現編譯器錯誤
  。它可以防止如 "if (PyList_SET_ITEM (a, b, c) < 0) ..." 測試之類的錯
  誤。（由 Zackery Spytz 和 Victor Stinner 在 bpo-30459 中貢獻。）

* 非受限 API 檔案 "odictobject.h"、"parser_interface.h"、
  "picklebufobject.h"、"pyarena.h"、"pyctype.h"、"pydebug.h"、
  "pyfpe.h" 和 "pytime.h" 已移至 "Include/cpython" 目錄。這些檔案不得
  直接被引入，因為它們已於 "Python.h" 中引入；請參閱 引入檔案 (include
  files)。如果直接引入它們，請考慮改為引入 "Python.h"。（由 Nicholas
  Sim 在 bpo-35134 中貢獻。）

* Use the "Py_TPFLAGS_IMMUTABLETYPE" type flag to create immutable
  type objects. Do not rely on "Py_TPFLAGS_HEAPTYPE" to decide if a
  type object is mutable or not; check if "Py_TPFLAGS_IMMUTABLETYPE"
  is set instead. (Contributed by Victor Stinner and Erlend E. Aasland
  in bpo-43908.)

* 未以說明文件記錄的函式 "Py_FrozenMain" 已從受限 API 中刪除。該函式主
  要用於 Python 的自定義建置。（由 Petr Viktorin 在 bpo-26241 中貢獻。
  ）


已棄用
------

* "PyUnicode_InternImmortal()" 函式現已棄用，並將在 Python 3.12 中刪除
  ：請改用 "PyUnicode_InternInPlace()"。（由 Victor Stinner 在
  bpo-41692 中貢獻。）


已刪除
------

* 刪除了操作 "Py_UNICODE*" 字串的 "Py_UNICODE_str*" 函式。（由 Inada
  Naoki 在 bpo-41123 中貢獻。）

  * "Py_UNICODE_strlen"：使用 "PyUnicode_GetLength()" 或
    "PyUnicode_GET_LENGTH"

  * "Py_UNICODE_strcat"：使用 "PyUnicode_CopyCharacters()" 或
    "PyUnicode_FromFormat()"

  * "Py_UNICODE_strcpy"、"Py_UNICODE_strncpy"：使用
    "PyUnicode_CopyCharacters()" 或 "PyUnicode_Substring()"

  * "Py_UNICODE_strcmp"：使用 "PyUnicode_Compare()"

  * "Py_UNICODE_strncmp"：使用 "PyUnicode_Tailmatch()"

  * "Py_UNICODE_strchr"、"Py_UNICODE_strrchr"：使用
    "PyUnicode_FindChar()"

* 刪除了 "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_RECURSION" 和
  "Py_END_ALLOW_RECURSION" 以及 "PyInterpreterState" 結構的
  "recursion_ritic" 欄位。（由 Serhiy Storchaka 在 bpo-41936 中貢獻。
  ）

* 刪除了未被說明文件記錄的 "PyOS_InitInterrupts()" 函式。初始化 Python
  已經隱式安裝信號處理程式：請參閱 "PyConfig.install_signal_handlers"
  。（由 Victor Stinner 在 bpo-41713 中貢獻。）

* 刪除 "PyAST_Validate()" 函式。不再可能使用公開 C API 來建置 AST 物件
  （"mod_ty" 類型）。該函式已被排除在受限 C API 之外 (**PEP 384**)。（
  由 Victor Stinner 在 bpo-43244 中貢獻。）

* 刪除 "symtable.h" 標頭檔和未被說明文件記錄的函式：

  * "PyST_GetScope()"

  * "PySymtable_Build()"

  * "PySymtable_BuildObject()"

  * "PySymtable_Free()"

  * "Py_SymtableString()"

  * "Py_SymtableStringObject()"

  "Py_SymtableString()" 函式錯誤地成為穩定 ABI 的一部分，但它因為
  "symtable.h" 標頭檔被排除在受限 C API 之外而無法使用。

  請改用 Python "symtable" 模組。（由 Victor Stinner 在 bpo-43244 中貢
  獻。）

* 從受限 C API 標頭和 "python3.dll" （在 Windows 上提供穩定 ABI 的函式
  庫）中刪除 "PyOS_ReadlineFunctionPointer()"。由於該函式採用 FILE* 引
  數，因此無法保證其 ABI 穩定性。（由 Petr Viktorin 在 bpo-43868 中貢
  獻。）

* 刪除 "ast.h"、"asdl.h" 和 "Python-ast.h" 標頭檔。這些函式沒有文件記
  錄，並且被排除在受限 C API 之外。這些標頭檔定義的大多數名稱都沒有前
  綴 "Py"，因此可能會產生名稱衝突。例如，"Python-ast.h" 定義了一個
  "Yield" 巨集，它與 Windows "<winbase.h>" 標頭使用的 "Yield" 有名稱衝
  突。請改用 Python "ast" 模組。（由 Victor Stinner 在 bpo-43244 中貢
  獻。）

* 刪除編譯器和使用 "struct _mod" 的剖析器函式，因為公開 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 中貢獻。）

* 為了 Python 最佳化，已刪除 "PyThreadState.use_tracing" 成員。（由
  Mark Shannon 在 bpo-43760 中貢獻。）


Notable security feature in 3.10.7
==================================

Converting between "int" and "str" in bases other than 2 (binary), 4,
8 (octal), 16 (hexadecimal), or 32 such as base 10 (decimal) now
raises a "ValueError" if the number of digits in string form is above
a limit to avoid potential denial of service attacks due to the
algorithmic complexity. This is a mitigation for CVE-2020-10735. This
limit can be configured or disabled by environment variable, command
line flag, or "sys" APIs. See the integer string conversion length
limitation documentation.  The default limit is 4300 digits in string
form.


Notable security feature in 3.10.8
==================================

The deprecated "mailcap" module now refuses to inject unsafe text
(filenames, MIME types, parameters) into shell commands. Instead of
using such text, it will warn and act as if a match was not found (or
for test commands, as if the test failed). (Contributed by Petr
Viktorin in gh-98966.)


Notable changes in 3.10.12
==========================


tarfile
-------

* The extraction methods in "tarfile", and "shutil.unpack_archive()",
  have a new a *filter* argument that allows limiting tar features
  than may be surprising or dangerous, such as creating files outside
  the destination directory. See Extraction filters for details. In
  Python 3.12, use without the *filter* argument will show a
  "DeprecationWarning". In Python 3.14, the default will switch to
  "'data'". (Contributed by Petr Viktorin in **PEP 706**.)
