如何为Mypy类型注释指定OrderedDict K,V类型?

时间:2016-12-18 09:38:12

标签: python python-3.5 mypy

我正在使用Python 3.5和Mypy对我的脚本进行一些基本的静态检查。最近我重构了一些返回OrderedDict的方法,但是当我尝试使用指定了Key和Value类型的返回注释时,遇到了''type'对象不能下标“错误。

简化示例:

#!/usr/bin/env python3.5

from collections import OrderedDict

# this works
def foo() -> OrderedDict:
    result = OrderedDict() # type: OrderedDict[str, int]
    result['foo'] = 123
    return result

# this doesn't
def foo2() -> OrderedDict[str, int]:
    result = OrderedDict() # type: OrderedDict[str, int]
    result['foo'] = 123
    return result

print(foo())

这是运行时的python输出:

Traceback (most recent call last):
  File "./foo.py", line 12, in <module>
    def foo2() -> OrderedDict[str, int]:
TypeError: 'type' object is not subscriptable

Mypy在评论中对类型注释没有任何问题,如果我尝试result[123] = 123,实际上会发出警告。

造成这种情况的原因是什么?

4 个答案:

答案 0 :(得分:15)

mypy没有问题(至少不是0.501)。 但是 是Python 3.6.0的一个问题。 请考虑以下事项:

from collections import OrderedDict
from typing import Dict

def foo() -> Dict[str, int]:
    result: OrderedDict[str, int] = OrderedDict()
    result['two'] = 2
    return result

此代码将满足mypy(0.501)和Python(3.6.0)。 但是,如果您将Dict替换为OrderedDict,那么mypy仍然会感到满意,但执行它会因TypeError: 'type' object is not subscriptable而死亡。

有趣的是,Python解释器在查看函数签名中的下标OrderedDict时死亡,但很高兴在变量类型注释中接受它。

无论如何,我的解决方法是在函数签名中使用Dict而不是OrderedDict(并添加注释,如果/当Python解释器学会接受时,应该修复此问题正确的签名)。

答案 1 :(得分:3)

作为一种解决方法,您还可以将返回类型放入字符串中,以同时满足Mypy和Python 3.6:

from collections import OrderedDict

def foo() -> 'OrderedDict[str, int]':
    result = OrderedDict()
    result['foo'] = 123
    return result

答案 2 :(得分:2)

您还可以尝试使用MutableMapping(如本答案:https://stackoverflow.com/a/44167921/1386610

from collections import OrderedDict
from typing import Dict

def foo() -> MutableMapping[str, int]:
    result = OrderedDict() # type: MutableMapping[str, int]
    result['foo'] = 123
    return result

答案 3 :(得分:2)

我不知道哪个版本允许这样做,但是对于 2021 年 3 月 24 日的更好的解决方案,已针对 Python 3.7.5 进行了测试:

from collections import OrderedDict
import typing

def foo() -> typing.OrderedDict[str, int]:
    result: typing.OrderedDict[str, int] = OrderedDict()
    result['two'] = 2
    return result

享受所有世界!