我正在使用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
,实际上会发出警告。
造成这种情况的原因是什么?
答案 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
享受所有世界!