是否可以在Python中对Annotated类型进行别名或子类化,并通过mypy验证



这些是我迄今为止使用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这样的特殊形式作为特例处理。

只有TupleCallableAny是特殊形式,它们是没有[]的有效类型,而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

最新更新