Python各个版本特性

1.2 Python版本特性

Python版本特性

1.2.1 Python3.5

PEP 492, 使用 async 和 await 语法实现协程。
PEP 465, 新的矩阵乘法运算符: a @ b。
PEP 448, 解包。
PEP 484,类型提示

1.2.1.1 PEP 448,解包

参照之前的Python基础教程中:解包(拆包)、装包章节。

1.2.1.2 PEP 484,类型提示

Python3.5首次新增了一个typing模块,用来对函数的形参及函数的返回类型标注。

def greeting(name: str) -> str:
    return 'Hello ' + name

在函数 greeting 中,参数 name 预期是 str 类型,并且返回 str 类型。
类型提示将在后续章节中重点介绍。

1.2.2 Python3.6

PEP 498, 格式化的字符串文字
PEP 515, 数字文字中的下划线。
PEP 526, 变量注释的语法。
PEP 525, 异步生成器。
PEP 530, 异步推导。

1.2.2.1 PEP 498,格式化的字符串文字:f-string

参照之前的Python基础教程中:f-string章节。

1.2.2.2 PEP 515,数字文字中的下划线

通过在数字中间添加_提高可读性。
>>> 1_000_000_000_000_000

1000000000000000

>>> 0x_FF_FF_FF_FF

4294967295

_只能插入数字中间,并且不能连续插入多个_,否则会报SyntaxError错:
>>> 100__000

Traceback (most recent call last):
File “C:\Program Files\Python3102\lib\code.py”, line 63, in runsource
code = self.compile(source, filename, symbol)
File “C:\Program Files\Python3102\lib\codeop.py”, line 185, in call
return _maybe_compile(self.compiler, source, filename, symbol)
File “C:\Program Files\Python3102\lib\codeop.py”, line 102, in _maybe_compile
raise err1
File “C:\Program Files\Python3102\lib\codeop.py”, line 91, in _maybe_compile
code1 = compiler(source + “\n”, filename, symbol)
File “C:\Program Files\Python3102\lib\codeop.py”, line 150, in call
codeob = compile(source, filename, symbol, self.flags, True)
File “”, line 1
100__000
^
SyntaxError: invalid decimal literal

1.2.2.3 PEP 526,变量注释

PEP 484 引入了函数形参类型标注即类型提示的标准。这个 PEP 为 Python 添加了标注变量类型的语法,包括类变量和实例变量:

from typing import List, Dict

primes: List[int] = []
captain: str  # Note: no initial value!
class Starship:
    stats: Dict[str, int] = {
    
    }

1.2.3 Python3.7

PEP 563,类型标注延迟求值。

1.2.4 Python3.8

PEP 572,赋值表达式。
PEP 570,仅限位置形参
f-string支持=

1.2.4.1 PEP 572,赋值表达式

赋值表达式:=可在表达式内部为变量赋值。它被昵称为“海象运算符”因为它很像是 海象的眼睛和长牙。
在这个示例中,赋值表达式可以避免调用 len() 两次:

if (n := len(a)) > 10:
print(f"List is too long ({
      
      n} elements, expected <= 10)")

类似的益处还可出现在正则表达式匹配中需要使用两次匹配对象的情况中,一次检测用于匹配是否发生,另一次用于提取子分组:

discount = 0.0
if (mo := re.search(r'(\d+)% discount', advertisement)):
    discount = float(mo.group(1)) / 100.0

此运算符也适用于配合 while 循环计算一个值来检测循环是否终止,而同一个值又在循环体中再次被使用的情况:

# Loop over fixed length blocks
while (block := f.read(256)) != '':
    process(block)

另一个值得介绍的用例出现于列表推导式中,在筛选条件中计算一个值,而同一个值又在表达式中需要被使用:

[clean_name.title() for name in names
 if (clean_name := normalize('NFC', name)) in allowed_names]

请尽量将海象运算符的使用限制在清晰的场合中,以降低复杂性并提升可读性。

1.2.4.2 PEP 570,仅限位置形参

参照之前的Python基础教程中:仅位置参数、仅关键字参数章节。

1.2.4.3 f-string支持=

增加=说明符用于f-string。 形式为 f’{expr=}’ 的 f-字符串将扩展表示为表达式文本,加一个等于号,再加表达式的求值结果。 例如:
>>> from datetime import date
>>> user = ‘eric_idle’
>>> member_since = date(1975, 7, 31)
>>> f’{user=} {member_since=}’

“user=‘eric_idle’ member_since=datetime.date(1975, 7, 31)”

通常的 f-字符串格式说明符允许更细致地控制所要显示的表达式结果:
>>> delta = date.today() - member_since
>>> f’{user=!s} {delta.days=:,d}’

‘user=eric_idle delta.days=16,075’

=说明符将输出整个表达式,以便详细演示计算过程:
>>> print(f’{theta=} {cos(radians(theta))=:.3f}')

theta=30 cos(radians(theta))=0.866

1.2.5 Python3.9

PEP 584,为 dict 增加合并运算符;
PEP 585,标准多项集中的类型标注泛型。
PEP 614,放宽对装饰器的语法限制。
PEP 616,移除前缀和后缀的字符串方法。

1.2.5.1 PEP 584,字典合并与更新运算符

合并 (|) 与更新 (|=) 运算符已被加入内置的 dict 类。它们为现有的 dict.update 和 {**d1, **d2} 字典合并方法提供了补充。
>>> x = {“key1”: “value1 from x”, “key2”: “value2 from x”}
>>> y = {“key2”: “value2 from y”, “key3”: “value3 from y”}
>>> x | y

{‘key1’: ‘value1 from x’, ‘key2’: ‘value2 from y’, ‘key3’: ‘value3 from y’}

>>> y | x

{‘key2’: ‘value2 from x’, ‘key3’: ‘value3 from y’, ‘key1’: ‘value1 from x’}

>>> x |= y
>>> x

{‘key1’: ‘value1 from x’, ‘key2’: ‘value2 from y’, ‘key3’: ‘value3 from y’}

1.2.5.2 PEP 616,移除前缀和后缀的字符串方法

str.removeprefix(prefix) 和 str.removesuffix(suffix) 用于方便地从字符串移除不需要的前缀或后缀。

s1 = 'abc.efg.apk'
print(s1.removeprefix('abc'))
print(s1.removesuffix('apk'))

.efg.apk
abc.efg.

1.2.6 Python3.10

PEP 604,允许 X | Y 形式的联合类型写法
PEP 612,形参规格变量
PEP 613,显式类型别名
PEP 626,在调试和其他工具中使用精确的行号。
PEP 634, 结构化模式匹配: 规范说明
PEP 635, 结构化模式匹配: 动机与理由
PEP 636, 结构化模式匹配: 教程
PEP 647, User-Defined Type Guards
bpo-12782,加圆括号的上下文管理器现在正式被允许使用。

1.2.6.1 带括号的上下文管理器

关于上下文管理器将在后续章节介绍。

1.2.6.2 更清楚的错误消息

1.2.6.2.1 SyntaxError

现在当解析包含有未关闭括号的代码时解释器会包括未关闭括号的位置而不是显示:
SyntaxError: unexpected EOF while parsing
并指向某个不正确的位置。例如,考虑以下代码(注意未关闭的 “ { ”):

expected = {
    
    9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
            38: 4, 39: 4, 45: 5, 46: 5, 47: 5, 48: 5, 49: 5, 54: 6,
some_other_code = foo()

之前版本的解释器会报告令人迷惑的语法错误位置:

File “example.py”, line 3
some_other_code = foo()
^
SyntaxError: invalid syntax

但在 Python 3.10 中则会发出信息量更多的错误提示:

File “example.py”, line 1
expected = {9: 1, 18: 2, 19: 2, 27: 3, 28: 3, 29: 3, 36: 4, 37: 4,
^
SyntaxError: ‘{’ was never closed

类似地,涉及未关闭字符串字面值 (单重引号和三重引号) 的错误现在会指向字符串的开头而不是报告 EOF/EOL。
这些改进的灵感来自 PyPy 解释器之前所进行的工作。
解释器所引发的 SyntaxError 异常现在将高亮构成语法错误本身的完整异常错误内容,而不是仅提示检测到问题的位置。 这样,不再(同 Python 3.10 之前那样)仅显示:
>>> foo(x, z for z in range(10), t, w)

File “”, line 1
foo(x, z for z in range(10), t, w)
^
SyntaxError: Generator expression must be parenthesized

现在 Python 3.10 将这样显示异常:
>>> foo(x, z for z in range(10), t, w)

File “”, line 1
foo(x, z for z in range(10), t, w)
^^^^^^^^^^^^^^^^^^^^
SyntaxError: Generator expression must be parenthesized

大量新增的专门化 SyntaxError 异常消息已被添加。 其中最主要的一些如下所示:
在代码块之前缺失“:”
>>> if rocket.position > event_horizon

File “”, line 1
if rocket.position > event_horizon
^
SyntaxError: expected ‘:’

在推导式的目标中有不带圆括号的元组:
>>> {x,y for x,y in zip(‘abcd’, ‘1234’)}

File “”, line 1
{x,y for x,y in zip(‘abcd’, ‘1234’)}
^
SyntaxError: did you forget parentheses around the comprehension target?

在多项集字面值中和表达式之间缺失逗号:
>>> items = {
… x: 1,
… y: 2
… z: 3,

File “”, line 3
y: 2
^
SyntaxError: invalid syntax. Perhaps you forgot a comma?

多个异常类型不带圆括号:
>>> try:
… build_dyson_sphere()
… except NotEnoughScienceError, NotEnoughResourcesError:

File “”, line 3
except NotEnoughScienceError, NotEnoughResourcesError:
^
SyntaxError: multiple exception types must be parenthesized

字典字面值中缺失“:”和值:
>>>
>>> values = {
… x: 1,
… y: 2,
… z:
… }

File “”, line 4
z:
^
SyntaxError: expression expected after dictionary key and ‘:’

>>> values = {x:1, y:2, z w:3}

File “”, line 1
values = {x:1, y:2, z w:3}
^
SyntaxError: ‘:’ expected after dictionary key

try 代码块不带 except 或 finally 代码块:
>>> try:
… x = 2
… something = 3

File “”, line 3
something = 3
^^^^^^^^^
SyntaxError: expected ‘except’ or ‘finally’ block

在比较中使用 = 而不是 ==:
>>> if rocket.position = event_horizon:

File “”, line 1
if rocket.position = event_horizon:
^
SyntaxError: cannot assign to attribute here. Maybe you meant ‘==’ instead of ‘=’?

在 f-字符串中使用 *:
>>> f"Black holes {*all_black_holes} and revelations"

File “”, line 1
(*all_black_holes)
^
SyntaxError: f-string: cannot use starred expression here

1.2.6.2.2 IndentationError

许多 IndentationError 异常现在具有更多上下文来提示是何种代码块需要缩进,包括语句的位置:
>>> def foo():
… if lel:
… x = 2

File “”, line 3
x = 2
^
IndentationError: expected an indented block after ‘if’ statement in line 2

1.2.6.2.3 AttributeError

当打印 AttributeError 时,PyErr_Display() 将提供引发异常的对象中类似属性名称的建议:
>>> collections.namedtoplo

Traceback (most recent call last):
File “”, line 1, in
AttributeError: module ‘collections’ has no attribute ‘namedtoplo’. Did you mean: namedtuple?

警告 请注意如果未调用 PyErr_Display() 来显示错误则此特性将没有效果,这可能发生在使用了某些其他自定义错误显示函数的时候。 这在某些 REPL 例如 IPython 上是一种常见的情况。

1.2.6.2.4 NameError

当打印解释器所引发的 NameError 时,PyErr_Display() 将提供引发异常的函数中类似变量名称的建议:
>>> schwarzschild_black_hole = None
>>> schwarschild_black_hole

Traceback (most recent call last):
File “”, line 1, in
NameError: name ‘schwarschild_black_hole’ is not defined. Did you mean: schwarzschild_black_hole?

警告 请注意如果未调用 PyErr_Display() 来显示错误则此特性将没有效果,这可能发生在使用了某些其他自定义错误显示函数的时候。 这在某些 REPL 例如 IPython 中是一种常见的情况。

1.2.6.3 结构化模式匹配(match语句)

参照之前的Python基础教程中:match语句 章节。

猜你喜欢

转载自blog.csdn.net/crleep/article/details/129961601