46

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

简化示例:

#!/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

5 回答 5

34

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)。但是,如果你用 替换DictOrderedDict那么 mypy 仍然会很高兴,但执行它会用TypeError: 'type' object is not subscriptable.

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

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

于 2017-04-24T09:10:22.590 回答
16

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

from collections import OrderedDict

def foo() -> 'OrderedDict[str, int]':
    result = OrderedDict()
    result['foo'] = 123
    return result
于 2018-10-03T11:39:30.603 回答
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
于 2017-08-11T13:26:00.457 回答
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

享受所有世界!

于 2021-03-24T11:52:24.187 回答
0

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())
于 2022-01-28T08:55:43.830 回答