查看原文
其他

很期待!尝鲜 Python 3.11 的 5 个新特性

南风草木香 Python开发者 2022-07-28

【导语】:本文主要介绍了Python 3.11的5个新特性,包括:更精确的错误提示,对CPython的优化,以及语法层面的新功能等。提前了解这些新特性有助于后期的使用。

简介

每年10月左右,都会发布Python的新版本。在每个版本发布前,都有17个月的开发周期,在此期间要进行持续的开发测试。首先会发布一个alpha版本,等到4月份再发布一个beta版本,直到最终的正式版本发布。本文将基于Python 3.11的alpha版本,介绍一些有趣的新特性。

安装

安装Python 3.11的方式有以下几种:

  • Docker安装

如果你的系统上可以使用Docker,可以直接运行如下命令安装:

docker pull python:3.11-rc-slim

接着运行:

docker run -it --rm python:3.11-rc-slim

关于Docker的详细信息可以查看:Docker[1]

  • 在Windows中安装

要在Windows操作系统上安装alpha版本,可以使用pyenv-win。更新pyenv-win后,就可以安装Python 3.11的alpha版本了。

pyenv update 
pyenv install 3.11.0a7

安装好后,就可以创建一个虚拟环境来测试该版本了。

pyenv local 3.11.0a7
python -m venv env
.\env\Scripts\activate
  • 在 Ubuntu/MacOS 中安装

安装方式与Windows中几乎一样,只是使用的命令有些区别:

$ pyenv update
$ pyenv install 3.11.0a7
$ pyenv virtualenv 3.11.0a7 311_preview
$ pyenv activate 311_preview

使用新特性

  1. 更精确的错误提示功能

Python的每一个新版本都在尝试改进错误处理功能,尤其是显示异常信息的traceback模块。Python 3.10就针对traceback模块做了一些改进。而在 Python 3.11 中,对错误的定位将更加精确,开发者可以直接看到引起错误的具体语法或对象。

在Python 3.11之前,traceback模块只会显示哪一行出了错误,具体的错误还需要开发者手动排查,而Python 3.11将直接标注出错误的具体位置,如下所示:

Traceback (most recent call last):
  File "distance.py", line 11, in <module>
    print(manhattan_distance(p1, p2))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "distance.py", line 6, in manhattan_distance
    return abs(point_1.x - point_2.x) + abs(point_1.y - point_2.y)
                           ^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'x'

我们可以看出:point_2 没有 x 这个属性。

当我们需要处理嵌套层级过多的字典对象或者调用多个函数时,更精确地错误提示将会很有帮助。例如下面这个例子:

Traceback (most recent call last):
  File "query.py", line 37, in <module>
    magic_arithmetic('foo')
    ^^^^^^^^^^^^^^^^^^^^^^^
  File "query.py", line 18, in magic_arithmetic
    return add_counts(x) / 25
           ^^^^^^^^^^^^^
  File "query.py", line 24, in add_counts
    return 25 + query_user(user1) + query_user(user2)
                ^^^^^^^^^^^^^^^^^
  File "query.py", line 32, in query_user
    return 1 + query_count(db, response['a']['b']['c']['user'], retry=True)
                               ~~~~~~~~~~~~~~~~~~^^^^^
TypeError: 'NoneType' object is not subscriptable

我们可以清晰的看到嵌套的函数中,出现错误的具体位置,从而及时修改代码。

新的错误查找特性还能帮助我们发现复杂算术表达式中的错误,假如我们用0做除数,解释器会显示错误的具体位置,示例如下:

raceback (most recent call last):
  File "calculation.py", line 54, in <module>
    result = (x / y / z) * (a / b / c)
              ~~~~~~^~~
ZeroDivisionError: division by zero

我们可以看到表达式 x / y / z 中用0做了除数,引发了错误。

  1. CPython 优化

CPython是用C语言实现的Python解释器。作为官方实现,它是最广泛使用的Python解释器。CPython3.11 要比 3.10 版本快25%,本次优化主要集中于启动和运行的速度。

  • 更快地启动

在3.11版本中,将在 __pycache__ 目录中缓存字节码,以提高加载模块的速度。Python解释器的启动速度有望提高10-15%。

  • 更快地运行

在Python中,每当调用用户自定义的函数时,都会创建栈帧(frame),栈帧表示程序运行时函数调用栈中的某一帧。以下是3.11版本对栈帧的优化,使其在运行时更快:

(1) 简化栈帧的创建过程,使其更快。

(2) 通过大量复用C栈上的空间来避免内存分配。

(3) 通过简化栈帧中的struct,来减少栈帧中的信息量。之前的栈帧包含额外的调试和内存管理信息,3.11版本中只有需要调试的时候才创建栈帧。

(4) 大多数情况下,无需使用栈帧对象。因此,运行速度将会提高3-7%。

  1. 新的类型特性:Self

在3.11版本中,有一个Self,可以对函数进行注释。函数注释主要用于给函数参数和返回值中添加元数据,从而指定函数参数的输入类型和返回值的类型。

例如,我们的代码中有一个类School,其中有个get_school方法,该方法可以返回School类的一个实例。之前如果我们想要注释函数,需要用到Typevar,过程比较繁琐:

from typing import TypeVar

TSchool = TypeVar('TSchool', bound='School'

class School:
    def get_school(self: TSchool) -> TSchool:
        return self

在3.11版本中,我们可以使用self类型:

from typing import Self

class School:
    def get_school(self) -> Self:
        return self
  1. except*处理多个异常

3.11版本中还有一个特性可以处理多个异常。该特性允许我们使用except*关键字和ExceptionGroup类同时处理多个异常。示例如下:

try:
    raise ExceptionGroup("Exception Group for multiple errors", (
        ValueError("This is a value error"),
        TypeError("This is a type error"),
        KeyError("This is a Key error"),
        AttributeError('This is an Attribute Error')
    ))

# 处理错误的不同方式
except* AttributeError: 
    ...
except* (ValueError, TypeError) as exc:
    ...
except* KeyError as exc:
    ...
  1. AsyncIO 任务组

对于前端开发者而言,这个特性很熟悉。该特性与JavaScript中的async/await语法很相似,AsyncIO 可以用来运行嵌套的任务,即使其中一个失败了,也可以继续运行。我们可以使用前面提到的特性4:ExceptionGroup,来实现TaskGroup特性。示例如下:

try:
    async with asyncio.TaskGroup() as tg:
        tg.create_task(t1())
        tg.create_task(t2())
except* ValueError as e:
    pass # 忽略所有的 ValueErrors

在该示例中,即使t1出错了,任务t2也会继续执行。

后记

这些是Python 3.11中一些有趣的新特性,如果你想了解更多新特性,可以在官方文档中查看[2]

参考资料[1]

Docker: https://hub.docker.com/_/python

[2]

官方文档中查看: https://docs.python.org/3.11/whatsnew/3.11.html

[3]

参考原文: https://levelup.gitconnected.com/5-new-features-in-python-3-11-that-makes-it-the-coolest-new-release-in-2022-c9df658ef813


- EOF -


加主页君微信,不仅Python技能+1

主页君日常还会在个人微信分享Python相关工具资源精选技术文章,不定期分享一些有意思的活动岗位内推以及如何用技术做业余项目

加个微信,打开一扇窗



推荐阅读  点击标题可跳转

1、快 45%,Python 3.11 性能表现优异

2、超全!Python 中常见的配置文件写法

3、源码探秘:Python 中对象是如何被调用的?


觉得本文对你有帮助?请分享给更多人

推荐关注「Python开发者」,提升Python技能

点赞和在看就是最大的支持❤️

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存