如何键入注释字典理解?

问题描述

Mypy 认为这对 strict = true 有效:

from typing import Dict,TypeVar

KeyType = TypeVar("KeyType")
ValueType = TypeVar("ValueType")


class InvertibleDict(Dict[KeyType,ValueType]):
    def __inverse__(self) -> "InvertibleDict[ValueType,KeyType]":
        new_instance: "InvertibleDict[ValueType,KeyType]" = self.__class__()
        for key,value in self.items():
            new_instance[value] = key
        return new_instance

但是,它不接受相同代码的以下更简洁版本,在最后一行说“关键字必须是字符串”:

from typing import Dict,KeyType]":
        return self.__class__(**{value: key for key,value in self.items()})

解决方法

MyPy 在这里是正确的,它捕捉实现中的错误(静态类型检查的美妙之处)。类型:

{value: key for key,value in self.items()}

Dict[KeyType,ValueType],但是这样做通常会失败:

dict(**some_mapping)

其中键不能保证是字符串

观察:

>>> dict(**{1:2,3:4})
Traceback (most recent call last):
  File "<stdin>",line 1,in <module>
TypeError: keywords must be strings

你只想:

return self.__class__({value: key for key,value in self.items()})

一般不会失败:

>>> dict({1:2,3:4})
{1: 2,3: 4}
    

就我个人而言,我会采用您的第一个实现,而不会不必要地浪费 2 倍所需的空间,并进行不必要的第二遍。

请注意,您可能永远不会使用 ** 解包来初始化 dict,构造函数的关键字参数形式为编写以下内容提供了便利:

>>> dict(foo=1,bar=2)
{'foo': 1,'bar': 2}

您甚至可以在复制字典但想要强制特定字符串键的值时使用这个方便的技巧:

>>> dict({'foo': 1,'bar': 2},bar=42)
{'foo': 1,'bar': 42}
,

只是为了笑我尝试了 return self.__class__({value: key for key,value in self.items()}),它似乎工作相同并通过了 mypy 检查。可以使用 dict 而不是 dict 来初始化 TIL **kwargs