我正在使用新的Python类型系统,遇到了我不知道如何表达的概念。我想传递通用类类型本身。例如。以描述使用通用 [1] G
的函数,键入T
并返回G[T]
。
我使用mypy
来检查我的尝试。
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
typing
的反向移植中的天真GenericMeta吗?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)
这是我现在使用的版本。
它捕获了apply(10, int)
之类的一些荒谬的调用,但是apply(int, int)
会经过静态分析并提高运行时间。
def apply(generic: Type, param: Type[T]) -> Type[Type[T]]:
return generic[param]
所以问题来了,可以表达泛型类型本身吗?
对于我来说,根据鸭子的类型,List
应该只是Mapping[Type, Type]
。我找到了protocols的PEP,也许这是解决我问题的正确工具?
[1] 如果我理解类别理论的正确性,则该泛型的类型在技术上被命名为functor,并且在Haskell等语言中是众所周知的概念。