Python 3.10的新特性

释放

3.10.0a4

日期

十月 23, 2021

本文将解释Python 3.10与3.9相比的新特性。

有关详细信息,请参阅 changelog .

注解

预发布用户应注意,此文档当前为草稿形式。随着Python3.10走向发布,它将得到实质性的更新,因此即使在阅读了早期版本之后,也值得检查。

总结——发布亮点

新特点

带括号的上下文管理器

现在支持在上下文管理器中跨多行使用括号继续。这允许以类似于以前使用IMPORT语句的方式格式化多行中的上下文管理器的长集合。例如,所有这些例子现在都是有效的:

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-12782bpo-40334 。)

PEP 563:延迟的批注评估成为默认值

在Python3.7中,添加了延迟的批注求值,可以使用 from __future__ import annotations 指令。在3.10中,即使没有未来的指令,这也成为默认行为。默认情况下,所有批注都存储在 __annotations__ 将是弦。如果需要,可以在运行时使用 typing.get_type_hints() 。看见 PEP 563 获取完整的描述。另外, inspect.signature() 将尝试从现在开始解析类型,当解析失败时,它将回退到显示字符串批注。(Batuhan Taskaya在 bpo-38605 。)

PEP 613:TypeAlias注释

PEP 484 引入了类型别名的概念,只要求它们是顶级的未注释赋值。这种简单性有时使类型检查器很难区分类型别名和普通赋值,特别是在涉及前向引用或无效类型时。比较::

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 604:新型并集运算符

引入了一种新类型的联合运算符,该运算符支持以下语法 X | Y 。这提供了一种更清晰的方式来表达“type X或type 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

看见 PEP 604 了解更多详细信息。

(Maggie Moss和Philippe Prados在 bpo-41428 。)

PEP 612:参数规范变量

用于改进提供给静电类型检查器的信息的两个新选项 PEP 484 ‘的 Callable 已添加到 typing 模块。

第一个是参数规范变量。它们用于将一个可调用函数的参数类型转发给另一个可调用函数--这是高阶函数和修饰符中常见的模式。用法示例可在 typing.ParamSpec 。以前,没有一种简单的方法可以如此精确地对参数类型的依赖项进行类型注释。

第二个选项是新的 Concatenate 接线员。它与参数规范变量结合使用,用于为高阶可调用对象添加或删除另一个可调用对象的参数的类型注释。用法示例可在 typing.Concatenate

看见 typing.Callabletyping.ParamSpectyping.ConcatenatePEP 612 了解更多详细信息。

(金肯在 bpo-41559 。)

解析器中更好的错误消息

分析包含未右括号或方括号的代码时,解释器现在包括未右括号的位置,而不是显示 语法错误:分析时出现意外的EOF 或者指向某个错误的位置。例如,请考虑以下代码(请注意未关闭的‘{’):

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

但是在Python3.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 和巴图汉·塔斯卡娅在 bpo-40176 。)

其他语言更改

  • 接受整数参数的内置函数和扩展函数不再接受 Decimal s, Fraction s和其他只能转换为整数且有损失的对象(例如 __int__() 方法,但没有 __index__() 方法)。(塞尔希斯托查卡在 bpo-37999

  • 赋值表达式现在可以在集合文字和集合理解中不加括号地使用,也可以在序列索引中使用(但不能在切片中使用)。

新模块

  • 还没有。

改进的模块

Arparse

在argparse帮助中,误导性短语“可选参数”已替换为“选项”。如果某些测试依赖精确的输出匹配,则可能需要进行调整。(Raymond Hettinger在 bpo-9694 。)

Base64

添加 base64.b32hexencode()base64.b32hexdecode() 支持扩展十六进制字母表的Base32编码。

解码器

添加 codecs.unregister() 函数注销编解码器搜索函数。(供稿人:海石 bpo-41842

collections.abc

这个 __args__parameterized genericcollections.abc.Callable 现在与 typing.Callablecollections.abc.Callable 泛型现在展平类型参数,类似于 typing.Callable 目前是这样的。这意味着 collections.abc.Callable[[int, str], str] 将会有 __args__(int, str, str) ;以前这是 ([int, str], str) 。要允许此更改, types.GenericAlias 现在可以子类化,并且在对 collections.abc.Callable 键入。请注意,一个 TypeError 对于无效的参数化形式可能引发 collections.abc.Callable 它可能已经在Python3.9中静默通过。(金肯在 bpo-42195 。)

Conextlib

添加 contextlib.aclosing() 上下文管理器安全地关闭异步生成器和表示异步释放的资源的对象。(由Joongi Kim和John Belmonte在 bpo-41229 。)

将异步上下文管理器支持添加到 contextlib.nullcontext() 。(Tom Gringauz在 bpo-41543 。)

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

双氮杂多糖(Distutils)

整个 distutils 软件包已弃用,将在Python 3.12中删除。它用于指定包版本的功能已经完全被第三方包取代 setuptoolspackaging ,并且大多数其他常用API在标准库中的其他位置可用(例如 platformshutilsubprocesssysconfig )。没有从迁移任何其他功能的计划 distutils ,并且使用其他函数的应用程序应该计划制作代码的私有副本。请参阅 PEP 632 以供讨论。

这个 bdist_wininst Python 3.8中不推荐使用的命令已删除。这个 bdist_wheel 现在,建议使用命令在Windows上分发二进制软件包。(Victor Stner在 bpo-42802 。)

文档测试

当模块没有定义 __loader__ ,后退到 __spec__.loader 。(Brett Cannon在 bpo-42133 。)

编码

encodings.normalize_encoding() 现在忽略非ASCII字符。(作者:海石在 bpo-39337 。)

格洛布

增加了 root_dirdir_fd 中的参数 glob()iglob() 它允许指定用于搜索的根目录。(塞尔希斯托查卡在 bpo-38144

检查

当模块没有定义 __loader__ ,后退到 __spec__.loader 。(Brett Cannon在 bpo-42133 。)

已添加 GLOBALNS当地人 参数位于 signature()inspect.Signature.from_callable() 检索给定本地和全局命名空间中的注释。(Batuhan Taskaya在 bpo-41960 。)

线卡

当模块没有定义 __loader__ ,后退到 __spec__.loader 。(Brett Cannon在 bpo-42133 。)

操作系统

补充 os.cpu_count() 支持VxWorks RTOS。(文中裴兴新供稿) bpo-41440

添加了一个新功能 os.eventfd() 和相关的帮助器来包装 eventfd2 Linux上的系统调用。(Christian Heimes在 bpo-41001 。)

已添加 os.splice() 这允许在两个文件描述符之间移动数据,而无需在内核地址空间和用户地址空间之间复制,其中一个文件描述符必须引用管道。(Pablo Galindo在 bpo-41625 。)

路径库

将切片支持添加到 PurePath.parents 。(Joshua Cannon在 bpo-35498 )

将负索引支持添加到 PurePath.parents 。(雅罗斯拉夫·潘科维奇在 bpo-21041 )

站台

已添加 platform.freedesktop_os_release() 要从检索操作系统标识,请执行以下操作 freedesktop.org os-release 标准文件。(Christian Heimes在 bpo-28468 )

py_compile

补充 --quiet 命令行界面选项 py_compile . (作者:Gregory Schevchenko bpo-38731

货架

这个 shelve 模块现在使用 pickle.DEFAULT_PROTOCOL 默认情况下,而不是 pickle 协议 3 在创建货架时。(Zackery Spytz在 bpo-34204 。)

站点

当模块没有定义 __loader__ ,后退到 __spec__.loader 。(Brett Cannon在 bpo-42133 。)

插座

例外情况是 socket.timeout 现在是的别名 TimeoutError 。(Christian Heimes在 bpo-42413 。)

系统

添加 sys.orig_argv 属性:传递给Python可执行文件的原始命令行参数的列表。(作者:Victor Stinner bpo-23427

添加 sys.stdlib_module_names ,包含标准库模块名称的列表。(Victor Stner在 bpo-42955 。)

穿线

已添加 threading.gettrace()threading.getprofile() 检索由设置的函数 threading.settrace()threading.setprofile() 分别为。(Mario Corchero在 bpo-42251 。)

添加 threading.__excepthook__ 若要允许检索的原始值,请执行以下操作 threading.excepthook() 以防它设置为损坏或不同的值。(Mario Corchero在 bpo-42308 。)

回溯

这个 format_exception()format_exception_only() ,以及 print_exception() 函数现在可以将异常对象作为仅限位置的参数。(Zackery Spytz和Matthias Bussonnier在 bpo-26389 。)

类型

重新引入 types.EllipsisTypetypes.NoneTypetypes.NotImplementedType 类,提供一组可由类型检查器轻松解释的新类型集。(作者:巴斯范比克 bpo-41810

打字

的行为 typing.Literal 已更改为符合 PEP 586 并与PEP中指定的静电类型检查器的行为相匹配。

  1. Literal 现在对参数执行重复数据消除。

  2. 两国之间的平等比较 Literal 对象现在与顺序无关。

  3. Literal 比较现在尊重类型。例如, Literal[0] == Literal[False] 之前评估为 True 。现在是时候了 False 。为了支持此更改,内部使用的类型缓存现在支持区分类型。

  4. Literal 对象现在将引发 TypeError 如果它们的一个参数不是 immutable 。请注意,声明 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 。)

单元测试

添加新方法 assertNoLogs() 补充现有的 assertLogs() . (作者:吉仁财供稿 bpo-39385

XML

添加 LexicalHandler 类到 xml.sax.handler 模块。(作者:Jonathan Gossage和Zackery Spytz bpo-35018

Zipimport

添加与 PEP 451find_spec()zipimport.zipimporter.create_module() ,以及 zipimport.zipimporter.exec_module() 。(Brett Cannon在 bpo-42131

优化

  • 施工人员 str()bytes()bytearray() 现在速度更快(对于小物体来说大约是30-40%)。(作者:Serhiy Storchaka in bpo-41334

  • 这个 runpy 模块现在导入的模块更少。这个 python3 -m module-name 命令启动时间平均快1.3倍。(作者:Victor Stinner bpo-41006

  • 这个 LOAD_ATTR 指令现在使用新“每操作码缓存”机制。现在它大约快了36%。这使得优化 LOAD_ATTR 说明当前最高性能的属性访问方法(比插槽更快)。(Pablo Galindo和Yury Selivanov在 bpo-42093 ,基于最初在PyPy和MicroPython中实现的思想。)

  • 使用构建Python时 --enable-optimizations 现在 -fno-semantic-interposition 添加到编译和链接行中。这加快了使用创建的Python解释器的构建速度 --enable-shared 使用 gcc 高达30%。看见 this article 了解更多详细信息。(Victor Stner和Pablo Galindo在 bpo-38980 。)

  • 函数参数及其注释不再在运行时计算,而是在编译时计算。它们被存储为字节码级别的字符串元组。现在,使用参数注释创建函数的速度大约提高了100%。(Yurii Karabas和Inada Naoki在 bpo-42202 )

已弃用

  • 从这个版本开始,将齐心协力开始清理旧的导入语义,这些语义是为了与Python2.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中删除。请参阅 module changes 部分了解更多信息。

  • 的非整数参数 random.randrange() 都已弃用。这个 ValueError 不推荐使用,而是支持 TypeError 。(Serhiy Storchaka和Raymond Hettinger在 bpo-37319 。)

  • 各式各样的 load_module() 方法: importlib 已记录为从Python3.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 。)

  • sqlite3.OptimizedUnicode 自Python3.3以来一直没有文档记录且已过时,当时它被用作别名 str 。它现在已弃用,计划在Python3.12中删除。(Erlend E.Aasland在 bpo-42264 。)

  • 未记录的内置函数 sqlite3.enable_shared_cache 现在已弃用,计划在Python 3.12中删除。SQLite3文档强烈反对使用它。看见 the SQLite3 docs 了解更多详细信息。如果必须使用共享缓存,请使用 cache=shared 查询参数。(Erlend E.Aasland在 bpo-24464 。)

远离的

  • 删除了特殊方法 __int____float____floordiv____mod____divmod____rfloordiv____rmod____rdivmod__complex 班级。他们总是举起一个 TypeError 。(Serhiy Storchaka在 bpo-41974 。)

  • 这个 ParserBase.error() 方法 _markupbase 模块已移除。 html.parser.HTMLParser 是的唯一子类 ParserBase 及其 error() Python3.5中的实现已经被删除。(作者:Berker Peksag in bpo-31844

  • 删除了 unicodedata.ucnhash_CAPI 属性,该属性是内部PyCapsule对象。与之相关的私人 _PyUnicode_Name_CAPI 结构已移至内部C API。(Victor Stner在 bpo-42157 。)

  • 删除了 parser 模块,由于切换到新的PEG解析器,以及所有仅由旧解析器使用的C源代码和头文件,在3.9中已弃用,包括 node.hparser.hgraminit.hgrammar.h

  • 删除了Public C API函数 PyParser_SimpleParseStringFlags()PyParser_SimpleParseStringFlagsFilename()PyParser_SimpleParseFileFlags()PyNode_Compile() 由于切换到新的PEG解析器,在3.9中已弃用。

  • 删除了 formatter 模块,该模块在Python3.4中已弃用。它有点过时,很少使用,也没有经过测试。它最初计划在Python3.6中删除,但这样的删除被推迟到Python2.7 EOL之后。现有用户应该将他们使用的任何类复制到他们的代码中。(由纳东熙和Terry J.Redy在 bpo-42299 。)

  • 删除了 PyModule_GetWarningsModule() 在2.6中,由于_WARNINGS模块而无用的函数在2.6中被转换为内置模块。(作者:海石在 bpo-42599 。)

  • 将不推荐使用的别名删除到 集合抽象基类collections 模块。(Victor Stner在 bpo-37324 。)

  • 这个 loop 参数已从大多数 asyncio ‘的 high-level API 在Python3.8中不推荐使用。这一变化背后的动机是多方面的:

    1. 这简化了高级API。

    2. 从Python3.7开始,高级API中的函数一直隐式获取当前线程的运行事件循环。在大多数正常用例中,不需要将事件循环传递给API。

    3. 事件循环传递容易出错,尤其是在处理在不同线程中运行的循环时。

    请注意,低级API仍将接受 loop 。看见 Changes in the Python API 有关如何替换现有代码的示例,请参阅。

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

移植到Python3.10

本节列出了前面描述的更改和可能需要更改代码的其他错误修复。

Python API中的更改

CPython字节码更改

  • 这个 MAKE_FUNCTION 指令接受字符串元组作为注释,而不是接受字典。(Yurii Karabas和Inada Naoki在 bpo-42202 )

建立变化

  • C99的功能 snprintf()vsnprintf() 现在需要构建Python。(作者:Victor Stinner bpo-36020

  • sqlite3 需要SQLite 3.7.15或更高版本。(Sergey Fedoseev和Erlend E.Aasland贡献) bpo-40744bpo-40810 。)

  • 这个 atexit 模块现在必须始终构建为内置模块。(Victor Stner在 bpo-42639 。)

  • 已添加 --disable-test-modules 选项添加到 configure 脚本:不要构建或安装测试模块。(Xavier de Gaye,Thomas Petazzoni和Peixing Xin在 bpo-27640 。)

  • 添加 --with-wheel-pkg-dir=PATH 选项添加到 ./configure 剧本。如果指定,则 ensurepip 模块查找 setuptoolspip 此目录中的车轮软件包:如果两者都存在,则使用这些车轮软件包,而不使用Ensurepip捆绑的车轮软件包。

    一些Linux发行版打包策略建议不要捆绑依赖项。例如,Fedora在 /usr/share/python-wheels/ 目录,并且不要安装 ensurepip._bundled 包裹。

    (Victor Stner在 bpo-42856 。)

C API更改

新特点

移植到Python3.10

已弃用

远离的