Skip to main content

3.9【2020-10】

🌟新增

官方地址

1、运算符-合并和更新字典(“|”和“|=”)

  • 合并运算符 “|”
# 不使用运算符
dict3 = {**dict1, **dict2}

# 使用运算符
dict3 = dict1 | dict2
  • 更新运算符 "|="
# 传统使用 .update
dict1.update(dict2)

# 使用运算符
dict1 |= dict2
  • 对 Iterables 进行更新
a = {'a': 'one', 'b': 'two'} 
b = ((i, i**2) for i in range(3))

a |= b print(a) {'a': 'one', 'b': 'two', 0: 0, 1: 1, 2: 4}

2、zoneinfo 时区模块(DateTime 支持 IANA 时区)

from zoneinfo import ZoneInfo
from dateTime import datetime

dt = datetime(2000, 01, 25, 01, tzinfo=ZoneInfo("America/Los_Angeles"))

3、graphlib

4、新型字符串函数:删除前缀和后缀

  • str.removeprefix() - 去除字符串前缀

  • str.removesuffix() - 去除字符串后缀

与.strip()的区别:

# 传统.strip() 无法解决

5、生成随机字节

Python 3.9 版本中添加了新的函数 random.Random.randbytes()。该函数可用于生成随机字节。

Python 支持生成随机数,但如果需要生成随机字节呢?在 Python3.9 版本之前,开发人员必须想方设法生成随机字节。尽管他们可以使用 os.getrandom()、os.urandom() 或者 secrets.token_bytes() 来生成随机字节,但这些方法无法生成伪随机模式。

为了确保随机数的产生符合预期行为,并且过程可复现,开发人员通常将种子(seed)与 random.Random 模块一起使用。因此,Python 3.9 添加了 random.Random.randbytes() 方法,以可控的方式生成随机字节。

✴优化

1、内置模块优化

模块名改进
ast
asyncio
concurrent.futures新参数 cancel_futures,可以取消尚未执行的并发任务。在 Python 3.9 之前主进程只有在所有并发任务完成后才能关闭 executor 对象。
新参数 cancel_futures 已被添加到 ThreadPoolExecutor 以及 ProcessPoolExecutor。它的工作方式是:当参数的值为 True 时,在调用 shutdown() 函数时取消所有待处理的任务。
multiprocessing
xml

2、修复字符串替换函数

在 Python 3.9 版本之前,对于所有非零的 n,"".replace("",s,n) 返回空字符串而不是 s。这个错误使用户困惑,并导致应用程序的不一致行为。

Python 3.9 修复了该问题,不管 n 是否为 0,其结果都与 "".replace("", s) 一致。

"".replace("", "blog", 1)
Returns ’'One would expect to see blog"".replace("","|", 1)
Returns ’'One would expect to see |"".replace("","prefix")
Howver returns ’prefix'

3、内置类型能直接用于类型声明

不再需要从 typing 导入 大写类型才能使用的 x[xxxx]语法了,内置类型可以直接指定list[type]

def greet_all(names: list[str]) -> None:
for name in names:
print("Hello", name)

4、异步编程和多进程优化

Python 3.9 对异步编程(asyncio)和多进程库进行了优化。

  1. 由于安全问题的考虑,asyncio.loop.create_datagram_endpoint() 不再支持参数 reuse_address。

  2. 新增了 coroutines、shutdown_default_executor() 和 asyncio.to_thread() 。shutdown_default_executor 负责关闭默认 executor,asyncio.to_thread() 主要用于在一条单独的线程中运行 IO 密集型函数,以避免事件循环。

关于多进程库的改进,Python 3.9 向 multiprocessing.SimpleQueue 类添加了新方法 close()。

此方法可以显式地关闭队列。这将确保队列关闭并且停留时间不会比预期长。值得注意的是,一旦关闭队列,就不能调用 get()、put() 和 empty() 方法。

5、统一的软件包导入错误

Python3.9 之前的版本在导入 Python 库时存在的主要问题是:当相对导入超出其顶级包时,Python 中的导入行为不一致。

builtins.import() 引发 ValueError,而 importlib.import() 引发 ImportError。Python3.9 版本进行了修复,它将统一引发 ImportError。

6、__import__()特性修改

import() 现在会引发 ImportError 而不是 ValueError。

至于原因,在Python的官方文档中有相应的解释:后者曾经会在相对导入超出其最高层级包时发生。

7、最小公倍数(LCM)

在Python 3.9中,不再需要定义自己的LCM函数,它新增了计算最小公倍数功能:

import math
math.lcm(49, 14) #98

Python长期以来一直具有用于计算两个数字的最大公约数(GCD)的功能:

import math
math.gcd(49, 14) # 7

8、IPv6范围内的地址

IPv6范围用于指定相应IP地址在Internet的哪个部分有效。

范围可以使用%符号在IP地址的末尾指定——例如:3FFE:0:0:1:200:F8FF:FE75:50DF%2——因此该IP地址在范围2中,即链接本地地址。

因此,如果需要使用Python处理IPv6地址,现在可以这样处理:

from ipaddress import IPv6Address addr = IPv6Address('ff02::fa51%1') print(addr.scope_id) #"1" - interface-local IP address

9、解释器从LL(1) 替换为 PEG

大约30年前,吉多·范·罗森写了pgen,这是为 Python 编写的第一批代码之一,至今仍被用作Python的解析器。Pgen的编写基于LL(1)的语法变体,这标志着解析器若要全方位读取代码,只需先行令牌。这也基本上说明Python的开发是有限的,因为:

· 先行令牌限制了语法规则的表现力。

· 由于当前Python已包含非LL(1)语法,解析器迂回方案繁杂,使过程复杂化。

· 即使有这些解决方案,情况也很受限。规则可以改变但不能违反。

· 使用LL(1)特定的左递归语法可能会使解析树分析无限循环,从而导致栈溢出。

基于LL(1)的解析器的这些属性限制了Python可能实现的价值,而Python 3.9打破了这些限制,这要归功于闪亮新星PEG解析器,PEP617有所概述。我们不会很快感受到这一点。在Python 3.10出来之前,新解析器不会更改;但之后,Python将会冲破LL(1)的限制,大显身手。

🗑弃用

1、不再支持window7

常见的软件升级通常有两种策略:第一:if it don't break, don't upgrade。只要还能用,就打死不升级。第二:always brand-new。所有部件永远保持最新版本。第一种策略常见于生产环境,第二种策略嘛,常见与发烧友与折腾党的开发机。Win7是一个已经有十三年历史的旧版本,如果一个系统保持如此旧版本的系统,那么通常采用的是第一个策略,在这种情况下,其它软件的版本也都不应该升级。包括python。所以python3.9是否支持这个系统并没有关系。第二种策略的Windows用户,现在肯定已经升级到了Win10,甚至Win11,所以python3.9支持这些用户就足够了。你不能指望一个操作系统还用13年前版本的用户,对python却非要升级到最新,相信我,他们一定也懒得升级python的。既然他们本来就不会升级python,新版本何必要支持?