在Python中,我很难定义类型.我想要这样的东西:

def foo(x: int) -> int:
    return x
    
def bar(x: str) -> str:
    return x

# [...] MyDictType would be defined here...
        
my_dict: MyDictType = {
    int: foo,       # Good
    str: bar,       # Good
    float: bar      # WRONG! Type warning!
}

MyDictType应指示它是将类型与接收该类型的变量的可调用对象映射的字典.我在想怎么用泛型来做这件事.但我不确定.我试过这个:

T = TypeVar("T")

MyDictType = dict[Type[T], Callable[[T], T]]

然而,编辑没有在词典的第三个条目中显示我预期的错误...

如何定义MyDictType?

推荐答案

没有办法做到这一点.任何批注都不能表达各个Dict键的类型与其相应值之间的关系.

您能得到的最接近的结果是定义一个包装器:

from collections.abc import Callable
from typing import Any, TypeVar

T = TypeVar('T')

class TypeMapperThing:
    _mapping: dict[type, Callable[[Any], Any]]
    def __init__(self):
        self._mapping = {}
    def __getitem__(self, key: type[T]) -> Callable[[T], T]:
        return self._mapping[key]
    def __setitem__(self, key: type[T], value: Callable[[T], T]) -> None:
        self._mapping[key] = value
    def __delitem__(self, key: type[T]) -> None:
        del self[key]

在这里,包装器隐藏了对Any的使用,并提供了类型安全的外部API.(我本可以省略Callable的类型参数,只编写_mapping: dict[type, Callable],但这将使用Callable[..., Any]而不是Callable[[Any], Any].不过,这无关紧要.)

请注意,没有好的方法可以让__init__接受DICT,或者编写接受DICT的update方法.试图这样做会遇到最初的问题,即试图为该词典编写一种类型.

我也避免使用collections.abc.Mappingcollections.abc.MutableMapping,因为这些ABC定义的接口遇到了与dict类似的问题.

Python相关问答推荐

使用numpy提取数据块

如何比较numPy数组中的两个图像以获取它们不同的像素

试图找到Python方法来部分填充numpy数组

需要计算60,000个坐标之间的距离

使用miniconda创建环境的问题

什么相当于pytorch中的numpy累积ufunc

如何让程序打印新段落上的每一行?

当从Docker的--env-file参数读取Python中的环境变量时,每个\n都会添加一个\'.如何没有额外的?

梯度下降:简化要素集的运行时间比原始要素集长

Scrapy和Great Expectations(great_expectations)—不合作

用渐近模计算含符号的矩阵乘法

如何从pandas DataFrame中获取. groupby()和. agg()之后的子列?

计算机找不到已安装的库'

使用polars. pivot()旋转一个框架(类似于R中的pivot_longer)

如何将返回引用的函数与pybind11绑定?

如何编辑此代码,使其从多个EXCEL文件的特定工作表中提取数据以显示在单独的文件中

BeatuifulSoup从欧洲志愿者服务中获取数据和解析:一个从EU-Site收集机会的小铲子

将像素信息写入文件并读取该文件

我如何处理超类和子类的情况

使用元组扩展字典的产品挑战