这些是我迄今为止使用Python 3.10:的尝试
from typing import Annotated, NewType, TypeAlias
AsTypeAlias: TypeAlias = Annotated
# Annotated[...] must have exactly one type argument and at least one annotation
AsNewType = NewType('AsNewType', Annotated)
# Argument 2 to NewType(...) must be a valid type; Annotated[...] must have exactly one type argument and at least one annotation
AsVariableAssignment = Annotated
# no error
Test: AsVariableAssignment[str, 'annotation']
# Variable "annotation_test.AsVariableAssignment" is not valid as a type; Name "annotation" is not defined
class AsSubClass(Annotated):
pass
# INTERNAL ERROR - mypy crashes
我是不是想做一些不该做的事?
就像模块typing
中的一些其他类型一样,Annotate
不是一个正则类型,而是一种特殊形式,可以在带有[]
的注释中用作类型。如果没有[]
,Annotation
就不是有效的类型。您不能将其别名,也不应该将其子类化。
类型别名
TypeAlias
允许显式地将别名为类型,而Annotated
则不允许。
AsTypeAlias: TypeAlias = Annotated
# Annotated[...] must have exactly one type argument and at least one annotation
NewType
出于同样的原因,这是无效的。如果没有[]
,Annotated
就不是有效的类型。
AsNewType = NewType('AsNewType', Annotated)
# Argument 2 to NewType(...) must be a valid type; Annotated[...] must have exactly one type argument and at least one annotation
类型别名的隐式定义
在Python中,您可以显式创建类型别名(在PEP613中使用TypeAlias
(,也可以通过Alias = SomeType
隐式创建。
对于后一种情况,类型检查器的一个关键任务是找出语义=
。它是常规变量赋值还是隐式类型别名定义?
考虑之间的差异
MyInt = int
# No error
def foo(a: MyInt): ...
和
MyInt = 5
# Variable "alt.MyInt" is not valid as a type
def foo(a: MyInt): ...
第一个示例隐式创建类型别名,而第二个示例创建变量。这看起来微不足道,但实际上反映了类型检查器通过检查赋值右侧表达式的类型来决定MyInt
是否应该是类型别名。当我们尝试进行时也是如此
AsVariableAssignment = Annotated
mypy需要知道RHS是否是有效类型。它将像Annotated
这样的特殊形式作为特例处理。
只有Tuple
、Callable
、Any
是特殊形式,它们是没有[]
的有效类型,而Annotated
不是其中之一。因此,mypy推断AsVariableAssignment = Annotated
是变量赋值,因为Annotated
不是有效类型,导致错误Variable "annotation_test.AsVariableAssignment" is not valid as a type
,因为它将AsVariableAssignment
视为变量。
'annotation'
不是Literal['annotation]
Mypy认为'annotation'
是一个字符串类型,所以它会查找一个名为annotation
的类型的定义,在这种情况下,应该使用Literal['annotation']
。此错误与Annotated
无关。
AsVariableAssignment = Annotated
# no error
Test: AsVariableAssignment[str, 'annotation']
# Variable "annotation_test.AsVariableAssignment" is not valid as a type; Name "annotation" is not defined
子类
许多特殊的表单不能被子类化,mypy通常会给出这样的错误:
# error: Invalid base class "Union"
class AsSubClass(Union):
pass
而下面的崩溃mypy。这可能是一个应该报告的错误。
class AsSubClass(Annotated):
pass
这是回溯。
error: INTERNAL ERROR -- Please try using mypy master on Github:
https://mypy.readthedocs.io/en/stable/common_issues.html#using-a-development-mypy-build
Please report a bug at https://github.com/python/mypy/issues
version: 0.930
Traceback (most recent call last):
File "mypy/semanal.py", line 5132, in accept
File "mypy/nodes.py", line 1005, in accept
File "mypy/semanal.py", line 1105, in visit_class_def
File "mypy/semanal.py", line 1127, in analyze_class
File "mypy/semanal.py", line 1337, in clean_up_bases_and_infer_type_variables
File "mypy/semanal.py", line 1428, in get_all_bases_tvars
File "mypy/types.py", line 615, in accept
File "mypy/typeanal.py", line 1296, in visit_unbound_type
IndexError: tuple index out of range