根据 Python 软件基金会 (PSF) 的说法,Python 3.11 处于其第 7 次 alpha 修订版中,计划于2022 年 10 月发布。
即将发布的版本包含哪些更改?
序言
为了评估版本 3.10 和 3.11 之间的差异,我设置了 2 个 docker 容器。
3.10 版的第一个容器:
docker run -t -d python:3.10.4-bullseye
3.11 版的第二个容器:
docker run -t -d python:3.11-rc-bullseye
运行两个容器后,我可以使用vs code 远程容器附加到正在运行的容器。
然后我可以在两个环境中执行我的 Python 代码并查看差异。
在接下来的部分中,我将首先展示一个代码示例,然后我将展示两个版本之间的差异。
1:错误位置
版本 3.10 中的输出:
1
100
Traceback(最近一次调用最后一次):
文件“/usr/local/lib/python3.10/runpy.py”,第 196 行,在 _run_module_as_main
返回 _run_code(代码,main_globals,无,
文件“/usr/local/lib /python3.10/runpy.py”,第 86 行,在 _run_code
exec(code, run_globals)
文件“/root/py310/myapp/__main__.py”,第 4 行,在 <module>
print(d["key_11"] )
KeyError: 'key_11'
版本 3.11 中的输出
1
100
Traceback(最近一次调用最后):
文件“<frozen runpy>”,第 198 行,_run_module_as_main
文件“<frozen runpy>”,第 88 行,_run_code
文件“/root/py311/myapp/__main__.py”,第 4 行,在 <module>
print(d["key_11"])
~
^^^^^^^^^^ KeyError: 'key_11'
Python 3.11 向开发人员公开了一个更好的错误位置,从而提供了很棒的开发人员体验。
2:’self’
类型
该self
类型已在typing extensions
模块中引入,现在已升级为标准类型库。
上面的代码代表了一个目录的结构。目录有子目录,所以定义是递归的。
Python 3.10 中的输出:
回溯(最后一次调用):
文件“/usr/local/lib/python3.10/runpy.py”,第 196 行,在 _run_module_as_main
返回 _run_code(代码,main_globals,无,
文件“/usr/local/lib/python3 .10/runpy.py”,第 86 行,在 _run_code
exec(code, run_globals)
文件“/root/py310/myapp/__main__.py”,第 2 行,在 <module>
中输入 import List, Tuple, Self
Python 3.11 中的输出:
{'content': (['a.txt', 'b.txt'],
[{'content': (['file1', 'file2'], None), 'name': 'dir1'}]) ,
'名称': 'dir2'}
subdir
注意:您可以通过类本身的名称来注释 的类型。但是,如果父类名称发生更改,您必须相应地更改所有注释引用。
为了使此代码在 3.11 和 3.10 中工作,您可以按如下方式执行导入:
尝试:
从输入 import Self
除了 ImportError:
从 typing_extensions import Self
3:异常说明
该类BaseException
现在有一个__note__
类属性,默认为None
.
您可以使用您选择的任何字符串覆盖它并提供更多信息。
Python 3.10 中的输出:
回溯(最后一次调用):
文件“/usr/local/lib/python3.10/runpy.py”,第 196 行,在 _run_module_as_main
返回 _run_code(代码,main_globals,无,
文件“/usr/local/lib/python3 .10/runpy.py",第 86 行,在 _run_code
exec(code, run_globals)
文件 "/root/py310/myapp/__main__.py",第 6 行,在 <module>
raise MyException("some exception")
__main__ 中。 MyException:一些异常
Python 3.11 中的输出:
回溯(最后一次调用):
文件“<frozen runpy>”,第 198 行,_run_module_as_main
文件“<frozen runpy>”,第 88 行,_run_code
文件“/root/py311/myapp/__main__.py”,第 6 行, 在 <module>
raise MyException("some exception")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
MyException:一些例外
,这是我的笔记:)
我们看到注释已添加到输出中,它允许开发人员在他们的异常中进行更多的交流。
4:异常组
3.11 版引入了一个新的异常类型名称ExceptionGroup
来抛出一组异常并在一个except
子句中处理它们。
除此之外,except*
还引入了一种新语法。
Python 3.10 中的输出:
文件“/usr/local/lib/python3.10/runpy.py”,第 189 行,在 _run_module_as_main
mod_name、mod_spec、code = _get_main_module_details(_Error)
文件“/usr/local/lib/python3.10/runpy.py”中,第 223 行,在 _get_main_module_details 中
返回 _get_module_details(main_name)
文件“/usr/local/lib/python3.10/runpy.py”,第 157 行,在 _get_module_details
代码 = loader.get_code(mod_name)
文件“<frozen importlib._bootstrap_external> ",第 1017 行,get_code
文件 "<frozen importlib._bootstrap_external>",第 947 行,source_to_code
文件 "<frozen importlib._bootstrap>",第 241 行,_call_with_frames_removed
文件 "/root/py310/myapp/__main__.py" ,第 18 行
除了 * (ToYoungException, EmailIsInvalidException) 作为 exception_group_1:
Python 3.11 中的输出:
验证失败
+ 异常组回溯(最后一次调用):
| _run_module_as_main 中的文件“<frozen runpy>”,第 198 行
| _run_code 中的文件“<frozen runpy>”,第 88 行
| 异常组:(1 个子异常)
+-+---------------- 1 ----------------
| 异常组回溯(最近一次调用最后一次):
| 文件“/root/py311/myapp/__main__.py”,第 14 行,在 <module>
| raise ExceptionGroup(
| ^^^^^^^^^^^^^^^^^^^^^
| ExceptionGroup: 数据验证(2 个子异常)
+-+----------- ----- 1 ----------------
| ToYoungException: Age must be over 18 - age is 11
+--------------- - 2 ----------------
| EmailIsInvalidException: 电子邮件必须是有效的 some_wannabe_email
+------------------------------------
|
| 上述异常是以下异常的直接原因:
|
| Traceback(最近一次通话最后一次):
| 文件“/root/py311/myapp/__main__.py”,第 20 行,在 <module>
| 从 exception_group_1 引发 ValueError
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ValueError
+------------------------------------
正如我们所看到的,当我们有多个失败原因想要一次性披露时,这是非常有价值的。
5. 嵌套的异步理解
Python 3.10 中的输出:
回溯(最近一次调用):
文件“/usr/local/lib/python3.10/runpy.py”,第 189 行,在 _run_module_as_main
mod_name、mod_spec、code = _get_main_module_details(_Error)
文件“/usr/local/lib/ python3.10/runpy.py”,第 223 行,在 _get_main_module_details 中
返回 _get_module_details(main_name)
文件“/usr/local/lib/python3.10/runpy.py”,第 157 行,在 _get_module_details
代码 = loader.get_code(mod_name)
文件“<frozen importlib._bootstrap_external>”,第 1017 行,在 get_code
文件“<frozen importlib._bootstrap_external>”,第 947 行,在 source_to_code
文件“<frozen importlib._bootstrap>”,第 241 行,在 _call_with_frames_removed
文件中/root/py310/myapp/__main__.py”,第 11 行
return { n: [x async for x in elements(n)] for n in range(3)}
^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^
SyntaxError:异步函数之外的异步理解
Python 3.11 中的输出:
{0: [1], 1: [1, 1], 2: [1, 2, 4], 3: [1, 3, 9, 27], 4: [1, 4, 16, 64, 256] }
代码进入理解块的那一刻,它现在知道关于其当前“函数上下文”的理解。
如果理解不是异步的,则内部代码块不能有异步语句。
但是,在 Python 3.11 中,如果它们包含async
允许内部推导的内部语句,推导就成为隐式异步的async
。
6:TOML解析器
TOML解析现在是标准库的一部分,就像 JSON 和 CSV 一样。
Python 3.10 中的输出:
回溯(最后一次调用):
文件“/usr/local/lib/python3.10/runpy.py”,第 196 行,在 _run_module_as_main
返回 _run_code(代码,main_globals,无,
文件“/usr/local/lib/python3 .10/runpy.py”,第 86 行,在 _run_code
exec(code, run_globals)
文件“/root/py310/myapp/__main__.py”,第 2 行,在 <module> 中
import tomllib
ModuleNotFoundError: No module named 'tomllib'
Python 3.11 中的输出:
{'clients': {'data': [['gamma', 'delta'], [1, 2]], 'hosts': ['alpha', 'omega']},
'database': {'connection_max ': 5000,
'enabled': True,
'ports': [8000, 8001, 8002],
'server': '192.168.1.1'},
'owner': {'dob': datetime.datetime(1979, 5, 27, 7, 32, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=57600))),
'name': 'Tom Preston-Werner'},
'servers': {'alpha': { 'dc': 'eqdc10', 'ip': '10.0.0.1'},
'beta': {'dc': 'eqdc10', 'ip': '10.0.0.2'}},
'title':'TOML 示例'}
7.性能优化
有人认为,与 python 3.10 相比,Python 3.11 的运行时间快 10-60%。