非 pep695 类型别名 (UP040)
源自 pyupgrade linter。
修复总是可用的。
作用
检查是否使用 TypeAlias
注解和 TypeAliasType
赋值来声明类型别名。
为什么这不好?
Python 3.12 通过 PEP 695 引入了 type
关键字,用于定义类型别名。type
关键字更易于阅读,并为泛型提供更简洁的支持。
已知问题
PEP 695 对类型参数使用推断的变异性,而不是 TypeVar
变量使用的 covariant
和 contravariant
关键字。因此,使用 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
赋值也是不安全的。
另请参阅
此规则仅适用于 TypeAlias
和 TypeAliasType
。有关泛型类和函数的类似转换,请参见 non-pep695-generic-class
和 non-pep695-generic-function
。
此规则替换别名中的独立类型变量,但即使在修复后未使用它们,也不会删除相应的类型变量。有关清理未使用的私有类型变量的规则,请参见 unused-private-type-var
。
即使新的类型参数的范围仅限于其关联的别名,此规则也不会重命名私有类型变量以删除前导下划线。有关更新这些名称的规则,请参见 private-type-parameter
。