Python 3.9 有哪些新变化?

2021-09-03 10:34:28 浏览数 (2292)

自从几个月前将最新的 Python 版本添加到 Ubuntu 21.04 以来,它在用户中变得越来越普遍。这为开发人员提供了充足的理由立即在他们的项目中开始使用它。因此,我们认为让大家了解最新版本提供了哪些功能是很有必要的——而且我们相信你们肯定也会喜欢这些功能!

新的字符串方法 ​str.removeprefix​ 和 ​str.removesuffix

这将成为粉丝最喜欢的功能,因为它解决了 Python 旧 ​str ​方法中一些混乱的东西 。

假设你想​​从文件名中删除扩展名​.py​,你会怎么做呢?你认为当然可以使用 ​str.rstrip​ 函数从字符串的右端去除扩展名,这个方方法是可以的:

>>> file_string = 'my_test_file.py'
>>> file_name = file_string.rstrip('.py')
>>> file_name
'my_test_file'

除了这一个致命的问题。看看你是否能找到这个输出的问题:

>>> file_string = 'make_happy.py'
>>> file_name = file_string.rstrip('.py')
>>> file_name
'make_ha'

为什么它删除了部分文件名?

嗯...这是因为 ​rstrip ​(以及 ​​lstrip ​and  ​strip​​)不接受“字符串”,而是一组要删除的字符。因此, ​file_string.rstrip('.py') ​并不意味着只删除  ​.py​​,它还意味着删除以下任何字符:  ​.​,  ​p​, and  ​y​,这就是为什么我们文件名末尾是ppy ​的也会被删除了。正是因为这个方法,在许多其他 ​Pythonistas ​中容易引起了错误和混乱。

这就是为什么Python的3.9添加了两个新方法: ​str.removeprefix​ 和 ​str.removesuffix​ ,它们会处理给定的字符串作为一个字符串:

>>> file_string = 'make_happy.py'
>>> file_name = file_string.removesuffix('.py')
>>> file_name
'make_happy'

新的 ​dict​ 合并和更新语法

Python 字典已经可以合并和更新,如下所示:

>>> alice = {'apples': 1, 'bananas': 2}
>>> bob = {'carrots': 3}
>>> merged = {**alice, **bob}  # Dictionary unpacking added in Python 3.5
>>> merged
{'apples': 1, 'bananas': 2, 'carrots': 3}
>>> alice
{'apples': 1, 'bananas': 2}
>>> alice.update(bob)          # Updates alice in-place with bob's values
>>> alice
{'apples': 1, 'bananas': 2, 'carrots': 3}

由于合并和更新是字典非常常用的功能(就像集合一样),这个新添加的操作简单地使这些操作更简单, | 操作符为:

>>> alice = {'apples': 1, 'bananas': 2}
>>> bob = {'carrots': 3}
>>> merged = alice | bob    # Merges the two into a new dictionary
>>> merged
{'apples': 1, 'bananas': 2, 'carrots': 3}
>>> alice
{'apples': 1, 'bananas': 2}
>>> alice |= bob            # Updates alice in-place
>>> alice
{'apples': 1, 'bananas': 2, 'carrots': 3}
>>>

标准集合中的类型提示泛型

我个人是这个功能的超级粉丝——如果你使用类型注释,你也会喜欢这个。在Python 3.9开始,你就可以开始使用所有内置集合类型:  list,  dict,  set, collections.deque 等你的类型的注释,而不是 typing.List, typing.Deque等,也不需要更多的 typing 导入!

# Previously:
from collections import defaultdict
from typing import DefaultDict, List, Set
 
values: List[int] = []
words: Set[str] = set()
counts: DefaultDict[int, int] = defaultdict(int)
# Starting from Python 3.9:
from collections import defaultdict
 
values: list[int] = []
words: set[str] = set()
counts: defaultdict[int, int] = defaultdict(int)

两个新模块

Python 3.9 引入了两个新模块:

  • zoneinfo ​这为标准库带来了对 IANA 时区数据库的支持。这意味着 Python 现在内置了对夏令时、国家全年时间变化等内容的支持。
  • graphlib​它具有拓扑排序算法的实现。因此,您现在拥有解决复杂图形问题的内置方法,例如在构建系统中对依赖项进行排序。

CPython 有一个新的、更强大的解析器

CPython ​现在使用基于​PEG​的新解析器 ,而不是基于旧的​LL1 ​算法的解析器。这意味着,对于可以将哪种语法添加到 Python 中存在某些限制,因为旧的解析器根本无法读取更复杂的代码。

多行with 语句就是一个例子 :

# Previously:
with open('file1.txt') as f1, \
        open('file2.txt') as f2:
    print(f1.read())
    print(f2.read())

通常你会在多行语句周围使用括号以获得更易读的行分组,并避免在行尾放置尾随 ​\-es​。

但是 Python 3.8 中的旧解析器不支持这种语法:

# Starting from Python 3.9:
with (
    open('file1.txt') as f1,
    open('file2.txt') as f2,
):
    print(f1.read())
    print(f2.read())

PEG 如果将来需要,新的和改进的 解析器算法将能够处理更复杂的语法解析。

其他补充

  • CPython采用年度发布周期,即每年发布一个新的CPython小版本。
  • random.Random.randbytes​ 生成随机字节的新 方法。
  • 该 ​__file__​ 内置变量始终是目前的绝对路径。
  • sys.stderr​ 从 Python 3.9 开始总是行缓冲。
  • ast ​模块更新:​​ 

             将 AST 转换回代码的新​ast.unparse方法。

             在​ ast.dump中() 添加  indent用于缩进的选项 ,类似于  json.dumps.

  • PEP 614​,放宽了对装饰器的语法限制。

概括

这个版本的 Python 为我们带来了许多方便的补充,同时也为解析器系统的更新和类型变化的更大功能奠定了基础。要更详细地了解此版本中的更改,你可以查看 文档