首页 > 解决方案 > 如何注释 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 等语言中是众所周知的概念。

标签: pythonpython-3.xpython-3.6python-3.7typing

解决方案


推荐阅读