用什么Python类型注释来表示通用类型类

时间:2019-11-06 05:48:37

标签: python mypy python-typing

在我的Python 3.7.4代码中,我具有以下功能。

def is_dict(klass: ???) -> bool:
    return klass.__origin__ == dict

我正在努力为klass参数获取类型注释。那不是mypy抱怨的type

  

错误:“ type”没有属性“ __origin__

我很茫然。什么是正确的注释,有关它的任何文档?

下面是如何使用此功能的示例:

>>> is_dict(typing.Dict[str, int])
True
>>> is_dict(typing.List[str])
False

2 个答案:

答案 0 :(得分:1)

如果您要使用注释中建议的类似GenericMeta的内容,或者尝试尝试创建定义适当的__origin__属性的自定义protocol,则首先需要更新typeshed中键入模块的类型提示以定义这些属性。

但是,目前,我建议仅使用Type[Any]Type[object]

from typing import Type, Any

# If you want to make minimal modifications to your code, make
# 'klass' dynamically typed.
def is_dict_1(klass: Type[Any]) -> bool:
    return klass.__origin__ == dict

# If you want to make your code robust, assume nothing about 'klass'
# except that it's some sort of type and verify the attribute you're
# about to use exists.
def is_dict_2(klass: Type[object]) -> bool:
    return getattr(klass, '__origin__', None) == dict

如果由于要创建某种序列化/反序列化库而专门尝试直接操作类型提示表达式,则还可以尝试查看pydantic之类的库的源代码灵感。

更广泛地讲,我还建议您探索尽可能减少代码中将类型提示表达式作为运行时实体进行操作的位置的可能性。 Python类型化生态系统在很大程度上是为了使静态世界和运行时世界保持分离而设计​​的,因此,将这两个世界融合在一起的机制并不是很方便使用,并且并不总是向后兼容。例如,自从在Python 3.5中首次发布以来,类型库的内部内容已经发生了多次更改。

答案 1 :(得分:0)

我已经编辑了答案:

import typing

def is_dict(klass: typing.GenericMeta) -> bool:
    return klass.__origin__ == typing.Dict

if __name__ == "__main__":
    print(is_dict(typing.Dict[str, int]))
    print(is_dict(typing.List[str]))

或者:

def is_dict(klass: typing.GenericMeta) -> bool:
        return klass.__orig_bases__[0] == dict