如何为 Mypy 类型注释指定 OrderedDict K,V 类型?
How do I specify OrderedDict K,V types for Mypy type annotation?
我正在使用 Python 3.5 和 Mypy 对我的脚本进行一些基本的静态检查。最近我将一些方法重构为 return OrderedDict,但是 运行 变成了“'type' object is not subscriptable” 错误,当我尝试使用 return 注释并指定了 Key 和 Value 类型时.
简化示例:
#!/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
。
这是什么原因造成的?
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
(并添加一条注释,说明应该修复 if/when Python 解释器将学会接受正确的签名)。
您还可以尝试使用 MutableMapping
(如本答案中所示:)
from collections import OrderedDict
from typing import Dict
def foo() -> MutableMapping[str, int]:
result = OrderedDict() # type: MutableMapping[str, int]
result['foo'] = 123
return result
作为解决方法,您还可以将 return 类型放入字符串中以满足 Mypy 和 Python 3.6:
from collections import OrderedDict
def foo() -> 'OrderedDict[str, int]':
result = OrderedDict()
result['foo'] = 123
return result
我不知道哪个版本允许这样做,但是 March/24/2021 的更好解决方案,针对 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
享受所有世界!
collections.OrderedDict 与 typing.OrderedDict
不同
from collections import OrderedDict as collections_OrderedDict
from typing import OrderedDict
# this works
def foo() -> OrderedDict[str, int]:
result = collections_OrderedDict()
result['foo'] = 123
return result
print(foo())
我正在使用 Python 3.5 和 Mypy 对我的脚本进行一些基本的静态检查。最近我将一些方法重构为 return OrderedDict,但是 运行 变成了“'type' object is not subscriptable” 错误,当我尝试使用 return 注释并指定了 Key 和 Value 类型时.
简化示例:
#!/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
。
这是什么原因造成的?
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
(并添加一条注释,说明应该修复 if/when Python 解释器将学会接受正确的签名)。
您还可以尝试使用 MutableMapping
(如本答案中所示:
from collections import OrderedDict
from typing import Dict
def foo() -> MutableMapping[str, int]:
result = OrderedDict() # type: MutableMapping[str, int]
result['foo'] = 123
return result
作为解决方法,您还可以将 return 类型放入字符串中以满足 Mypy 和 Python 3.6:
from collections import OrderedDict
def foo() -> 'OrderedDict[str, int]':
result = OrderedDict()
result['foo'] = 123
return result
我不知道哪个版本允许这样做,但是 March/24/2021 的更好解决方案,针对 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
享受所有世界!
collections.OrderedDict 与 typing.OrderedDict
不同from collections import OrderedDict as collections_OrderedDict
from typing import OrderedDict
# this works
def foo() -> OrderedDict[str, int]:
result = collections_OrderedDict()
result['foo'] = 123
return result
print(foo())