如何在 python 中定义这行代码以通过 mypy 检查

how to define this line of code in python in order to pass mypy checking

我的 python 代码中有这样的定义:

options = defaultdict(lambda: defaultdict(lambda: defaultdict(str)))
options['modem1']['ByCost'] = ...
options['modem1']['ByCarrier'] = ...
options['modem1']['BySimSignal'] = ...
options['modem1']['SwitchBackByTimer'] = ...

在我的 pre-commit/mypy 检查期间它失败了,因为消息是:

Need type annotation for 'options'

因为我没有发现此代码有任何问题,所以是否有任何解决方法可以让它通过 mypy 对此行的检查?

顺便说一句,除了在我的代码中设置它之外,我正在寻找替代方法:

disable_error_codes with error code var-annotated

非常感谢!

杰克

在 Python 3.9+、thanks to PEP 585 上,您可以使用 defaultdict 本身进行类型注释,使这变得简单,如果有点 redundant/verbose (请参阅答案底部3.9+ 的解决方案稍微少了一点 redundant/verbose,但不能轻松地向后移植到 3.8 和更早版本):

from collections import defaultdict

options: defaultdict[str, defaultdict[str, defaultdict[str, str]]] = defaultdict(lambda: defaultdict(lambda: defaultdict(str)))

请注意,这假设您实际上拥有三级 defaultdict;你的代码只下降了两层,所以如果你这样做,你会得到一个检查错误:

options['modem1']['ByCost'] = 'abc'

因为您确实需要多一级 str 键:

options['modem1']['ByCost']['xyz'] = 'abc'

如果你真的想要两层 defaultdict,trim 它回到:

options: defaultdict[str, defaultdict[str,str]] = defaultdict(lambda: defaultdict(str))

options['modem1']['ByCost'] = 'abc'

如果您使用的是 Python 3.8 或更早版本,请将使用 defaultdict 的注释替换为 typing.DefaultDict 注释,使其成为:

from collections import defaultdict
from typing import DefaultDict

options: DefaultDict[str, DefaultDict[str, DefaultDict[str, str]]] = defaultdict(lambda: defaultdict(lambda: defaultdict(str)))
# Or if only two levels:
options: DefaultDict[str, DefaultDict[str, str]] = defaultdict(lambda: defaultdict(str))

减少冗余解决方案

注意:3.9 用法允许您同时注释 使用注释类型,因此作为 3.9+ 唯一的解决方案,您可以这样做(为简单起见显示两层情况) :

options = defaultdict[str, defaultdict[str,str]](lambda: defaultdict(str))

并且不需要在 options 本身上显式提供注释,因为顶级 defaultdict 已经被注释,隐式注释它分配给的变量。