python - 如何注释 typing.Generic 类型本身?
问题描述
我正在玩新的 Python 类型系统,我遇到了我不知道如何在其中表达的概念。我想传递泛型类类型本身。例如,描述采用泛型[1] G
、 typeT
和return 的函数G[T]
。
我曾经mypy
检查验证我的尝试。
天真的方法在 Python 3.7 中不起作用。
from typing import Generic, Type, List, Mapping, TypeVar
T = TypeVar('T')
def foo(generic: Generic, param: Type[T]) -> Generic[T]: # error: Invalid type "typing.Generic"
return generic[param] # error: Value of type "Generic?[T?]" is not indexable
ListOfInts: Type = foo(List, int)
assert ListOfInts == List[int] # passes in runtime
Python 3.6 的后向移植中的朴素 GenericMeta typing
?
backport中有 GenericMeta 可用,但我没有找到如何使用它,也没有进入 PEP。
def foo(generic: GenericMeta, param: Type[T]) -> Type[Type[T]]:
return generic[param] # error: Value of type "GenericMeta" is not indexable
映射[类型,类型]?
我想出了Mapping
,但显然List
不是这样。
def apply(generic: Mapping[Type, Type], param: Type[T]) -> Type[Type[T]]:
return generic[param]
# error: Argument 1 to "apply" has incompatible type "Type[List[Any]]"; expected "Mapping[Type[Any], Type[Any]]"
ListOfInts: Type = apply(List, int)
在 Python 3.6 和 3.7 中不太严格的工作
这是我现在使用的版本。它捕获了一些荒谬的调用,例如apply(10, int)
,但apply(int, int)
会通过静态分析并在运行时引发。
def apply(generic: Type, param: Type[T]) -> Type[Type[T]]:
return generic[param]
那么问题来了,是否可以表达泛型类型本身?
至于我,基于鸭子打字,List
应该只是Mapping[Type, Type]
. 我找到了协议的 PEP ,也许这是解决我问题的正确工具?
[1]如果我对范畴论的理解正确,那么这种泛型的类型在技术上被称为函子,并且在 Haskell 等语言中是众所周知的概念。