跳到内容

非 pep695 类型别名 (UP040)

源自 pyupgrade linter。

修复总是可用的。

作用

检查是否使用 TypeAlias 注解和 TypeAliasType 赋值来声明类型别名。

为什么这不好?

Python 3.12 通过 PEP 695 引入了 type 关键字,用于定义类型别名。type 关键字更易于阅读,并为泛型提供更简洁的支持。

已知问题

PEP 695 对类型参数使用推断的变异性,而不是 TypeVar 变量使用的 covariantcontravariant 关键字。因此,使用 PEP-695 type 语句重写类型别名可能会改变别名类型参数的变异性。

与使用简单赋值的类型别名不同,使用 PEP 695 type 语句创建的定义不能在运行时用作语句右侧值的直接替换。这意味着,虽然对于一些简单的旧式类型别名,您可以将它们用作 isinstance() 调用的第二个参数(例如),但对 PEP 695 type 语句执行相同操作总会在运行时引发 TypeError

示例

from typing import Annotated, TypeAlias, TypeAliasType
from annotated_types import Gt

ListOfInt: TypeAlias = list[int]
PositiveInt = TypeAliasType("PositiveInt", Annotated[int, Gt(0)])

建议改为

from typing import Annotated
from annotated_types import Gt

type ListOfInt = list[int]
type PositiveInt = Annotated[int, Gt(0)]

修复安全性

由于上述围绕 isinstance() 调用的运行时行为,此修复对于存根文件之外的 TypeAlias 赋值标记为不安全。如果替换范围内有任何将被删除的注释,则该修复对于 TypeAliasType 赋值也是不安全的。

另请参阅

此规则仅适用于 TypeAliasTypeAliasType。有关泛型类和函数的类似转换,请参见 non-pep695-generic-classnon-pep695-generic-function

此规则替换别名中的独立类型变量,但即使在修复后未使用它们,也不会删除相应的类型变量。有关清理未使用的私有类型变量的规则,请参见 unused-private-type-var

即使新的类型参数的范围仅限于其关联的别名,此规则也不会重命名私有类型变量以删除前导下划线。有关更新这些名称的规则,请参见 private-type-parameter