版本新特性
PEP 是什么?
PEP 的全称是 Python Enhancement Proposals
,可以翻译为 Python 改进提案。PEP 完全由社区驱动,汇总了多方信息,经过了部分核心开发者 review 和认可,最终形成正式文档,起到了对外公示的作用。
PEP 的官网是:https://www.python.org/dev/peps/,这也就是 PEP 0 的地址。其它 PEP 的地址是将编号拼接在后面,例如:https://www.python.org/dev/peps/pep-0020/ 就是 PEP 20 的链接,以此类推。
官方将 PEP 分成三类:
- I - Informational PEP
- 信息类:这类 PEP 就是提供信息,有告知类信息,也有指导类信息等等。例如 PEP 20(The Zen of Python,即著名的 Python 之禅)、PEP 404 (Python 2.8 Un-release Schedule,即宣告不会有 Python2.8 版本)。
- P - Process PEP
- 流程类:这类 PEP 主要是 Python 本身之外的周边信息。例如 PEP 1(PEP Purpose and Guidelines,即关于 PEP 的指南)、PEP 347(Migrating the Python CVS to Subversion,即关于迁移 Python 代码仓)。
- S - Standards Track PEP
- 标准类:这类 PEP 主要描述了 Python 的新功能和新实践(implementation),是数量最多的提案。例如我之前提到过的 f-string 方式,它出自 PEP 498(Literal String Interpolation,字面字符串插值)。
Python 3.8
海象运算符
Assignment Exppresions,https://peps.python.org/pep-0572/
新增的语法 :=
可在表达式内部为变量赋值,帮你少写一行代码
a = [1, 2, 3, 4, 5, 6]
if (n := len(a)) > 5:
print(f"List is too long ({n} elements, expected <= 5)")
很像 Golang 中的这种写法:
import "fmt"
func main() {
if age := 20; age > 18 {
fmt.Println("已经成年了")
}
}
if (age:= 20) > 18:
print("已经成年了")
在推导式中也可以使用,通常用于减少执行的次数
# old
[abs(m) for m in members if abs(m) > 10]
# new
[abs_m for m in members if (abs_m := abs(m)) > 10]
函数形参语法 /
函数形参语法 /
用来指明某些函数形参必须是位置形参的形式(而非关键字形参的形式)
在下面的例子中,形参 a 和 b 只能是位置形参,c 或 d 可以是位置形参或关键字形参,而 e 或 f 只能是关键字形参:
def f(a, b, /, c, d, *, e, f):
print(a, b, c, d, e, f)
f(10, 20, 30, d=40, e=50, f=60) # ok
f(10, b=20, c=30, d=40, e=50, f=60) # b cannot be a keyword argument
f(10, 20, 30, 40, 50, f=60) # e must be a keyword argument
这个特性更多地被用在标准包中,比如 len()
(function) def len(
__obj: Sized,
/
) -> int
>>> a=[1,2,3]
>>> len(a)
3
>>> len(__obj=a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: len() takes no keyword arguments
f-string 支持 =
语法
形式为 f'{expr=}'
的 f 字符串将扩展表示为表达式文本,加一个等于号,再加表达式的求值结果。
from datetime import date
name = 'Nick'
birthday = date(2001, 6, 4)
print(f'{name=} {birthday=}')
# "user='Nick' birthday=datetime.date(2001, 6, 4)"
可以更细致地控制所要显示的表达式结果
delta = date.today() - birthday
print(f'{delta.days=:,d}')
# 'delta.days=8,164'
Python 3.9
字典的合并和更新
合并 (|) 与更新 (|=) 运算符已被加入内置的 dict 类,扩充了现有的 e 和 {**d1, **d2}
字典合并方法。
字典添加两个新的运算符,'|' 和 '|='。
|
用于合并字典,相当于dict.update
|=
用于更新,相当于{**d1, **d2}
a = {"k1": 1, "k2": 2}
b = {"k3": 3, "k4": 4}
print(a | b)
# {'k1': 1, 'k2': 2, 'k3': 3, 'k4': 4}
a = {"k1": 1, "k2": 2}
b = {"k2": 3, "k3": 4}
a |= b
print(a)
# {'k1': 1, 'k2': 3, 'k3': 4}
list 和 dict 成为通用类型
可以将 list 或 dict 直接作为列表和字典的类型注释,而不必依赖 typing.List 或者 typing.Dict
# old
from typing import Dict, List
def func(l: List[str], d: Dict[str, int]):
pass
# new
def func(l: list[str], d: dict[str, int]):
pass
Python 3.10
类型检查 Union 的更优替代
使用 |
代替 Union
# old:
from typing import Union
def func(value: Union[int, float]) -> Union[int, float]:
return value
# new:
def func(value: int | float) -> int | float:
return value
上下文管理器的优化
with 支持使用外层圆括号来使用多个上下文管理器,可以连续多行地书写
with (
open("somefile.txt") as some_file,
open("otherfile.txt") as other_file,
):
...
模式匹配(Pattern Matching)
类似于 switch/case 的一个语法
# 匹配字符串
def func(day):
match day:
case "Monday":
return "Here we go again..."
case "Friday":
return "Happy Friday!"
case "Saturday" | "Sunday": # Multiple literals can be combined with `|`
return "Yay, weekend!"
case _:
return "Just another day..."
# 匹配元组(拆包)
def match_person(person):
match person:
case (name, 'M', age):
print(f'He is {name}, aged {age}.')
case (name, 'F', age):
print(f'She is {name}, aged {age}.')
case (name,):
print(f'We only know the name is {name}, others are secrets.')
# 匹配对象
from dataclasses import dataclass
@dataclass
class Command:
command: str
arguments: list[str]
def run_command(command: Command):
match command:
case Command(command="load", arguments=[filename]):
print(f"Loading file: {filename}.")
case Command(command="save", arguments=[filename]):
print(f"Saving to file: {filename}.")
case Command(command="quit" | "exit" | "bye", arguments=["--force" | "-f"]):
print("Sending SIGTERM and quitting the program.")
quit()
case Command(command="quit" | "exit" | "bye"):
print("Quitting the program.")
quit()
case _:
print(f"Unknown command: {command!r}.")
Python 3.11
异常说明
在 except 子句中,可以调用 add_note()
在引发错误时传递自定义消息。
import math
try:
math.sqrt(-1)
except ValueError as e:
e.add_note("Negative value passed! Please try again.")
raise
typing.Self
函数的返回值是 self 或类本身的新实例,可以使用 typing.Self
from typing import Self
class SomeClass:
def __init__(self, a, b):
self.a = a
self.b = b
def change_b(self, b) -> Self:
self.b = b
return SomeClass(self.a, self.b)