即将到来的Python 3.9 新增功能展望

版权声明:本文为作者原创文章,转载请附上原文出处链接和本声明。
本文链接:https://www.weijc.cn/jdetail/380430471240096768

在Python3.8的首个正式版发布一年后,根据Python发版规律最新的Python版本为3.9,预计将在下个月发布第一个正式版本。那么Python 3.9能带来哪些更新和变化呢,请和虫虫一起展望学习一下。

新功能

字典合并和更新运算符

Merge(|)和update(|=)运算符已添加到内置dict类中。

例如:

a = {1: 'a', 2: 'b', 3: 'c'}

b = {4: 'd', 5: 'e'}

c = a | b

print(c)

结果为:

{1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}

也可以这么用:

a = {1: 'a', 2: 'b', 3: 'c'}

b = {4: 'd', 5: 'e'}

a |= b

print(a)

结果为:

{1: 'a', 2: 'b', 3: 'c', 4: 'd', 5: 'e'}

新的removeprefix()和removesuffix()字符串方法

str.removeprefix(prefix)并且 str.removesuffix(suffix)已添加,可以轻松地从字符串中删除不需要的前缀或后缀。相应的 bytes,bytearray和collections.UserString方法也已添加。

def removeprefix(self: str, prefix: str, /) -> str:

if self.startswith(prefix):

return self[len(prefix):]

else:

return self[:]

def removesuffix(self: str, suffix: str, /) -> str:

# suffix='' should not call self[:-0].

if suffix and self.endswith(suffix):

return self[:-len(suffix)]

else:

return self[:]

内置泛型类型

在类型注释中,现在可以使用内置的集合类型,例如list和dict作为通用类型,而不是从中导入相应的大写类型(例如List或Dict)typing。例如,标准库中的其他一些类型现在也通用了queue.Queue。

例:

def greet_all(names: list[str]) -> None:

for name in names:

print("Hello", name)

新解析器

Python 3.9使用了一个新的解析器,该解析器基于PEG而不是LL(1)。新解析器的性能大致可与旧解析器媲美,但是在设计新语言功能时,PEG形式主义比LL(1)更灵活。我们将在Python 3.10及更高版本中开始使用这种灵活性。

该ast模块使用新的解析器,并产生与旧解析器相同的AST。

在Python 3.10中,旧的解析器将被删除,依赖它的所有功能也将被删除(主要是parser早已弃用的模块)。

在Python 3.9中,可以使用命令行开关(-X oldparser)或环境变量(PYTHONOLDPARSER=1)切换回LL(1)解析器。

其他语言的变化

__import__()会抛出ImportError而非ValueError,这通常是在相对导入超出其顶级包时发生。

Python获取在命令行(例如:python3 script.py)上指定的脚本文件名的绝对路径,__main__模块的__file__属性变为绝对路径,而非相对路径。通过os.chdir()更改当前目录后,这些路径仍然有效。副作用是,在这种情况下,回溯还会显示模块框架__main__的绝对路径。

现在,在Python开发模式和调试版本中,将检查encoding和errors参数是否进行了字符串编码和解码操作。例如:open(),str.encode()和 bytes.decode()。

默认情况下,为了获得最佳性能,仅在出现第一个编码/解码错误时才检查errors参数,并且对于空字符串有时会忽略encoding参数。

".replace("", s, n),现在返回s非零值,而不是空字符串n。和"".replace("", s) 一样。与此相似,bytes和bytearray对象有类似的变化。

任何有效的表达式现在都可以用为装饰器。

改进了对typing模块的帮助。现在将显示所有特殊格式和特殊通用别名(如Union和List)的文档字符串。比如使用help()与范型别名一样List[int]会显示对应的具体类型的帮助。

新模块

zoneinfo

zoneinfo模块将对IANA时区数据库的支持引入标准库。它添加zoneinfo.ZoneInfo了datetime.tzinfo由系统时区数据支持的具体实现。

例:

>>> from zoneinfo import ZoneInfo

>>> from datetime import datetime, timedelta

>>> # Daylight saving time

>>> dt = datetime(2020, 10, 31, 12, tzinfo=ZoneInfo("America/Los_Angeles"))

>>> print(dt)

2020-10-31 12:00:00-07:00

>>> dt.tzname()

'PDT'

>>> # Standard time

>>> dt += timedelta(days=7)

>>> print(dt)

2020-11-07 12:00:00-08:00

>>> print(dt.tzname())

PST

作为未提供IANA数据库的平台的备用数据源,该tzdata模块以第一方包的形式发布-通过PyPI分发并由CPython核心团队维护。

graphlib

添加graphlib包含graphlib.TopologicalSorter该类的,以提供执行图的拓扑排序的功能。

标准库变化

AST

添加了缩进选项,以dump()使其产生多行缩进输出。ast.unparse()作为ast模块中的功能添加,可用于解析ast.AST对象并生成带有代码的字符串,该代码ast.AST在解析时会生成等效的对象。

向包含用于构造该节点的ASDL签名的AST节点添加了文档字符串。

asyncio

由于重大安全问题,删除了asyncio.loop.create_datagram_endpoint()的reuse_address参数支持。由于SO_REUSEADDRUDP中的套接字选项的行为,更多详细信息,请参见的文档loop.create_datagram_endpoint()。

添加了一个新的协程shutdown_default_executor() ,该协程计划为等待ThreadPoolExecutor结束关闭的默认执行程序安排关闭时间。另外, asyncio.run()已更新为使用新的协程。

添加了新的协程 asyncio.to_thread()。主要用于在单独的线程中运行IO绑定函数,以避免阻塞事件循环,并且本质上run_in_executor()是可以直接使用关键字参数的高级版本。

添加了asyncio.PidfdChildWatcher,它是Linux专用的子监视程序实现,用于轮询进程文件描述符。

compileall

增加hardlink_dupes参数和-hardlink-dupes命令行选项,用于对重复.pyc文件使用硬链接的。

在结果.pyc文件中添加了用于路径操作的新选项:stripdir,prependdir,limit_sl_dest参数以及-s,-p和-e命令行选项。添加了可多次为优化级别指定选项。

concurrent.futures

添加了一个新的cancel_futures参数,concurrent.futures.Executor. shutdown(),参数将取消所有尚未开始运行的未决futures,而不是在关闭执行程序之前等待它们完成。

从ThreadPoolExecutor 和中删除了守护进程线程ProcessPoolExecutor。这提高了与子解释器的兼容性以及其关闭过程的可预测性。

ProcessPoolExecutor的workers实现按需增加,当没有可用的空闲workers重用时才会新添加。该设置优化了启动开销,并减少了空闲工作者的CPU时间损失。

curses

添加curses.get_escdelay(),curses.set_escdelay(), curses.get_tabsize(),和curses.set_tabsize()功能。

datetime

isocalendar()和isocalendar()datetime.datetime方法,会返回namedtuple(),而非tuple。

distutils

现在,上载命令将创建SHA2-256和Blake2b-256哈希摘要。它会在阻止MD5摘要的平台上跳过MD5。

fcntl

新增的常量F_OFD_GETLK,F_OFD_SETLK 和F_OFD_SETLKW。

FTPLIB

构造了给定超时为零FTP而FTP_TLS会抛出一个ValueError,以防止非阻塞套接字的创建。

GC

当垃圾收集器进行一些对象复活的收集时(在完成终结器之后,可以从隔离的循环之外访问它们),请不要阻止所有仍无法访问的对象的收集。

添加了一个新功能,gc.is_finalized()以检查对象是否已由垃圾收集器完成。

hashlib

内置的哈希模块现在可以禁用(./configure --without-builtin-hashlib-hashes)或有选择地启用。

例如,通过./configure --with-builtin-hashlib-hashes=sha3,blake2

强制使用基于OpenSSL的实现。

HTTP

HTTP状态代码http.HTTPStatus新添加了"103 EARLY_HINTS" ,"418 IM_A_TEAPO"和"425 TOO_EARLY"。

IDLE和idlelib

添加选项以切换光标闪烁。

退出键现在关闭IDLE完成窗口。

将关键字添加到模块名称完成列表。

以上更改已经移植到了3.8维护版本。

imaplib

IMAP4和IMAP4_SSL支持一个可选的构造函数的超时参数。open()方法有一个可选的超时参数,并且覆盖的方法到IMAP4_SSL和 IMAP4_stream。

新增加imaplib.IMAP4.unselect()方法用于释放与所选邮箱关联的服务器资源,并使服务器返回到已验证状态。该命令执行操作与imaplib.IMAP4.close()相同,但unselect()它不会从当前选定的邮箱中永久删除任何邮件。

importlib

为了提高与导入语句的一致性,对于无效的导入尝试,importlib.util.resolve_name()引发而非ValueError。

inspect

inspect.BoundArguments.arguments从OrderedDict更改为常规dict.

ipaddress

ipaddress现在支持IPv6范围地址(带后缀的IPv6地址%<scope_id>)。

可以使用解析范围内的IPv6地址ipaddress.IPv6Address。如果存在,则可通过属性获得作用域区域ID。

Math

扩展了math.gcd()函数以处理多个参数。以前,它仅支持两个参数。

增加math.lcm():返回指定参数的最小公倍数。

增加math.nextafter():将x之后的下一个浮点值 向y返回。

增加math.ulp():返回浮点数的最低有效位的值。

multiprocessing

multiprocessing.SimpleQueue类新增加方法明确地关闭队列。

nntplib

如果给定超时为零,NNTP和NNTP_SSL会抛出一个ValueError以防止非阻塞套接字的创建。

OS

si_code新增加参数CLD_KILLED和CLD_STOPPED。

公开了Linux特定的os.pidfd_open()和 os.P_PIDFD函数用于使用文件描述符进行进程管理。

os.unsetenv()功能在Windows上也可用。

该os.putenv()和os.unsetenv()功能现在始终可用。

添加os.waitstatus_to_exitcode()功能:将等待状态转换为退出代码。

pathlib

添加pathlib.Path.readlink(),它表现和os.readlink()类似的行为。

poplib

如果给定超时为零,POP3会抛出一个,以防止非阻塞套接字的创建。

pprint

pprint现在可以漂亮打印了types.SimpleNamespace。

pydoc

现在不仅针对类,函数,方法等,所有有__doc__属性的对象都支持。

random

添加一个新random.Random.randbytes方法:生成随机字节。

signal

公开了Linux专有信息,signal.pidfd_send_signal()用于使用文件描述符而不是pid向进程发送信号。

smtplib

SMTP和MTP_SSL对给定超时为零设置会抛出一个ValueError,以防止非阻塞套接字的创建。

LMTP构造函数现在具有一个可选的timeout参数。

socket

socket模块可以CAN_RAW_JOIN_FILTERS 在Linux 4.1及更高版本上导出常量。在支持CAN_J1939协议的平台上支持该协议。

time

在AIX上,thread_time()现在实现的分辨率为thread_cputime()纳秒,而非clock_gettime(CLOCK_THREAD_CPUTIME_ID)的10毫秒。

sys

添加一个新sys.platlibdir属性:特定于平台的库目录的名称。它用于构建标准库的路径和已安装的扩展模块的路径。

"lib"在大多数平台上,它都相等。在Fedora和SuSE上,等于"lib64"在64位平台上。

以前sys.stderr在非交互式时是块缓冲的。现在stderr默认为始终是行缓冲的。

tracemalloc

添加tracemalloc.reset_peak()了将跟踪的内存块的峰值大小设置为当前大小,以测量特定代码段的峰值。

typing

PEP 593引入了一种typing.Annotated类型,以使用上下文特定的元数据和新include_extras参数 来修饰现有类型,typing.get_type_hints()以在运行时访问元数据。

unicodedata

Unicode数据库已更新至版本13.0.0。

VENV

venv现在提供的激活脚本都始终使用所指定的值来一致地指定其提示自定义__VENV_PROMPT__。以前,有些脚本是无条件使用的__VENV_PROMPT__,而其他脚本只有在碰巧被设置的情况下才使用(这是默认情况),而另一种则使用__VENV_NAME__。

XML

现在,当序列化为xml.etree.ElementTreeXML文件时,可以保留属性内的空格字符。EOLN不再标准化为" n"。这是关于如何解释XML规范2.11节的讨论的结果。

性能优化

优化了用于在理解中分配临时变量的惯用法。现在,for y in [expr]和一个简单的任务y = expr一样快。

例如:sums = [s for s in [0] for x in data for s in [s + x]]

与:=运算符不同,该惯用法不会将变量泄漏到外部作用域。

优化多线程应用程序中的信号处理。如果与主线程不同的线程收到信号,则字节码评估循环不再在每个字节码指令处中断,以检查无法处理的未决信号。只有主解释器的主线程可以处理信号。

以前,字节码评估循环在每条指令处都会中断,直到主线程处理信号为止。

使用subprocess来优化FreeBSD上的模块closefrom()。

以下是从Python 3.4到Python 3.9的性能改进:

结果基于Tools/scripts/var_access_benchmark.py基准脚本,脚本以纳秒为单位显示计时。基准测试是在运行python.org运行的macOS 64位版本的因特尔 Core i7-4960HQ处理器上进行的 。

许多的Python建宏(range,tuple,set,frozenset,list,dict)现在通过使用加速PEP 590矢量通话协议。

总结

本文我们列出了Python 3.9版本中的代理功能更新和标准库变化。注意,在正式版本发行前,Python的具体功能草案会不断地变化,请随时关注官方文档

展开阅读全文
还能输入1000个字符