Python 如何为Mypy类型批注指定OrderedDict K、V类型?

Python 如何为Mypy类型批注指定OrderedDict K、V类型?,python,python-3.5,typing,mypy,Python,Python 3.5,Typing,Mypy,我正在使用Python3.5和Mypy对脚本进行一些基本的静态检查。最近,我重构了一些方法以返回OrderedDict,但在尝试使用指定键和值类型的返回注释时,遇到了“'type'对象不可订阅”错误 简化示例: #!/usr/bin/env python3.5 from collections import OrderedDict # this works def foo() -> OrderedDict: result = OrderedDict() # type: Orde

我正在使用Python3.5和Mypy对脚本进行一些基本的静态检查。最近,我重构了一些方法以返回OrderedDict,但在尝试使用指定键和值类型的返回注释时,遇到了“'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
回溯(最近一次呼叫最后一次):
文件“/foo.py”,第12行,在
def foo2()->OrderedDict[str,int]:
TypeError:“type”对象不可下标
然而,Mypy对注释中的类型注释没有问题,并且如果我尝试执行
result[123]=123
,它实际上会发出警告


是什么导致了这种情况?

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”对象不可订阅

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


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

您还可以尝试使用
可变映射
(如下面的回答:)


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

from collections import OrderedDict

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

我不知道哪个版本允许这样做,但是对于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

享受所有的世界

它现在可以工作了(mypy版本0.501)。只需存放一个指向修复程序的链接:是的,最后,我在自己的代码中使用了相同的解决方法。这在mypy 0.063中导致了一个错误,但建议将函数签名更改为字符串的答案是有效的。Python
typing.OrderedDict
在3.7.2中引入的
typing.OrderedDict
在3.9中再次被弃用,这增加了对
collections.OrderedDict的支持[K,V]
。另一个解决方法是引用函数签名中的类型,例如,
“OrderedDict[…]”
对于3.7,我尝试了
建议:OrderedDict[str,Any]=OrderedDict()
但是在
OrderedDict()下有一个红色的曲线
泛型应该通过方括号指定
。但是简单地用[]替换()也不能解决这个问题,因为现在它需要在[]中有一个表达式。我不确定我是否理解这个问题。@U noob请准确地编写给出错误的代码。另外,您是否使用3.7.5+?我实际上使用的是3.8.7。是的,因此我使用Pycharm,它建议使用
[]
fix。我点击它让它修复,但现在它需要一个表达式。不确定我是否应该初始化一个没有类似建议的值:orderedict[str,Any]=orderedict[dummykey]
我甚至尝试了建议:orderedict[str,Any]={}
但随后linter警告说它需要OrderedDict,但得到了Dict。请尝试
建议:OrderedDict[str,Any]=OrderedDict()
建议[dummykey]=1
from collections import OrderedDict
import typing

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