优雅的 python 代码

1 列表推导式

列表推导式可以省略掉循环中创建空列表、迭代添加元素等操作,从而简化代码并提高执行效率。
列表推导式通常比循环更加简洁高效,而且在大多数情况下不会影响代码的可读性。

1
2
3
4
5
6
7
8
def get_group_names(self, user):
group_names = []
for g in user.groups.all():
group_names.append(g.name)
return group_names

def get_group_names(self, user):
return [g.name for g in user.groups.all()]

2 类型注解

2.1 typing 模块

2.1.1 Annotated

Annotated 是一种用于结合类型注解和附加元数据的新工具。它允许为类型添加额外的信息,用于描述类型的用途或约束,而不会影响类型本身的行为。

Annotated 的元数据不会影响代码的运行,但可以被静态类型检查工具(如 MyPy)或 IDE 插件读取,从而提高代码可读性和开发体验。

Annotated 接受以下参数:

  • 类型:第一个参数必须是一个具体的类型,比如 int、str、自定义类等。
  • 元数据:第二个及后续参数是元数据,可以是任意 Python 对象,通常是字符串、函数、类实例等。
1
2
3
4
from typing import Annotated

def get_group_names(self, user: Annotated[User, '用户对象']) -> list[str]:
return [g.name for g in user.groups.all()]

在上面的代码中,Annotated[User, '用户对象'] 表示 user 参数的类型注解,并添加了一个元数据 '用户对象' 用于描述 user 对象的用途。

比如下面介绍一种更典型的用法,比如结合 fastapi 框架,限制参数的范围:

典型用法
1
2
3
4
5
6
7
8
9
10
from typing import Annotated
from fastapi import Query, FastAPI

app = FastAPI()

@app.get("/items/")
async def read_items(
size: Annotated[int, Query(ge=1, le=100)] # 限制 size 的范围为 1 到 100
):
return {"size": size}
使用 Annotated 的典型用法2
1
2
3
4
5
6
from typing import Annotated

CustomAnnotated = Annotated[int, "Positive", {"max_value": 100}]

def process_value(value: CustomAnnotated) -> None:
pass

3 参考文献