首页 > 编程问答 >为什么参数类型“Dict[str, Union[str, int]]”不接受类型“Dict[str, str]”的值(mypy)

为什么参数类型“Dict[str, Union[str, int]]”不接受类型“Dict[str, str]”的值(mypy)

时间:2024-07-30 14:06:36浏览次数:13  
标签:python python-typing mypy

我有一个传递给模板的变量字典的类型:

VariablesDict = Dict[str, Union[int, float, str, None]]

基本上,任何字典,其中键是字符串,值是字符串、数字或 None。我在几个与模板相关的函数中使用这种类型。

以这个示例函数为例:

def render_template(name: str, variables: VariablesDict):
    ...

使用字典文字调用此函数效果很好:

render_template("foo", {"key": "value"})

但是,如果我首先将字典分配给变量,如下所示:| ||Mypy 给出错误:

variables = {"key": "value"}

render_template("foo", variables)

“render_template”的参数 2 具有不兼容的类型“Dict[str, str]”;预期“Dict [str,Union [int,float,str,None]]”

在我看来,任何

类型的值都应该安全地传递给需要 Dict[str, str] 类型参数的函数。为什么默认情况下不起作用?我能做些什么来让这项工作成功吗? Dict[str, Union[int, float, str, None]] . Why doesn't that work by default? Is there anything I can do to make this work?


遇到此行为的原因是,即使 Dict[str, str] 看起来像是 Dict[str, Union[int, float, str, None]] 的子类型,但类型提示在 Python 中的工作方式并非如此。让我们分解一下:

不变性与可变性

关键问题在于字典是一种可变数据结构。当将类型注释为 Dict[str, Union[int, float, str, None]] 时,是在说该字典可以存储字符串键以及可以是整数、浮点数、字符串或无的

现在,如果传递 Dict[str, str] ,它最初似乎是安全的,因为字符串值也符合联合类型。但是,问题在于 Dict[str, str] 类型的变量 以后 可能会被更新为包含的不仅仅是字符串。

请考虑以下示例:

def render_template(name: str, variables: Dict[str, Union[int, float, str, None]]):
    ...

variables: Dict[str, str] = {"key": "value"}  # Initially fine

render_template("foo", variables)

variables["another_key"] = 10  # 潜在问题!

在这个修改后的示例中,我们将一个整数值分配给 variables 字典中的一个新键。这在技术上对于 variables: Dict[str, str] 是有效的,但会破坏 render_template 函数的预期,该函数预计该字典的值只能是联合类型中的类型。

Mypy 的严格性

Mypy 旨在通过及早发现潜在错误来帮助。在的情况下,Mypy 正确地标记了类型不匹配,因为它不能保证 Dict[str, str] 将始终仅包含字符串值。

解决方案

可以通过以下几种方式解决此问题:

  1. 更具体的类型注释: 如果确定传递给 render_template 的字典将始终仅包含字符串值,可以简单地更新类型注释以匹配:

```python def render_template(name: str, variables: Dict[str, str]): ...

variables = {"key": "value"} render_template("foo", variables) ```

  1. 类型转换: 可以将传递给 render_template 的字典强制转换为 Dict[str, Union[int, float, str, None]]

python variables = {"key": "value"} render_template("foo", cast(Dict[str, Union[int, float, str, None]], variables))

  1. 使用 typing.TypedDict 对于更复杂的字典结构,其中需要对每个键具有特定的类型,可以使用 typing.TypedDict

```python from typing import TypedDict

class TemplateVariables(TypedDict): key: str another_key: Union[int, float, None]

def render_template(name: str, variables: TemplateVariables): ...

variables: TemplateVariables = {"key": "value", "another_key": 10} render_template("foo", variables) ```

总之, 虽然看起来违反直觉,但 Mypy 的行为旨在确保类型安全并防止运行时错误。通过理解 Python 中不变性和可变性的概念以及 Mypy 的严格性,可以编写更安全、更可靠的代码。

标签:python,python-typing,mypy
From: 73603289

相关文章

  • python之代码简化式(列表、字典生成式,递归函数,迭代器(iter)和生成器(yield)、匿名函数(
    文章目录前言1、列表、字典生成式2、递归函数2.1python中代码的递归深度(扩展)3、拓展:迭代器和生成器3.1迭代器(iter)3.2生成器(yield)4、匿名函数(lambda)4.1map函数4.2reduce函数(较少使用)4.3filter函数前言本文主要讲解一些简化代码格式的一些方法,方便大家更好的......
  • Python:在 Protocol 和 TypedDict 之间共享类型注释
    举这个简单的例子:from__future__importannotationsimporttypingastclassMyType:def__init__(self,s:str,i:int)->None:self.s=sself.i=iclassMyProto(t.Protocol):s:stri:intclassMyDict(t.TypedDict):......
  • PIL 和 python 静态类型
    我有一个函数参数,它可以接受图像的多种类型:defsomefunc(img:Union[np.array,Image,Path,str]):PILImage在这种情况下抛出以下异常:TypeError:Union[arg,...]:eachargmustbeatype.Got<module'PIL.Image'from...进一步检查图像对象后这才有......
  • 学会用Python爬取小说网站,想看什么就爬什么,广告也不用看了~
    今天以爬取笔趣阁小说网站为例,练习Python爬虫技术。通过这个爬虫,可以完成批量爬取一本小说的所有章节,并将所有章节内容按顺序保存到一个txt文档内,下面我们就开始吧。首先,百度搜索“笔趣阁”,发现有很多网站都叫笔趣阁。我们可以随便挑选一个网站尝试,本文我以‘https://......
  • 计算机毕业设计django+vue《Python数据分析》的教学系统【开题+论文+程序】
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景在当今数字化时代,数据分析已成为各行各业不可或缺的技能之一,而Python作为数据分析领域的首选语言,其重要性日益凸显。然而,传统的教学模式在......
  • 如何将多个变量分配给 python 函数中的单个参数?
    我正在尝试编写一个程序,如果可能的话,它需要一个三项式并对其进行因式分解。每当用户输入A、B和C时,三项式应该通过Factor(product,summation)函数获取,但我似乎无法弄清楚如何将A和C分配给乘积arg,将B分配给我尝试在函数外部声明不同的变量,product=(a*c)和summati......
  • python - 从文本生成音乐
    请给我一些建议为了解释一下,我输入“深度睡眠的睡眠音乐”,它将返回一个wav文件:https://www.youtube.com/watch?v=1wAdQhFJy54或者我给出一个wav文件,它会返回相同的现在这是我尝试过的:https://github.com/facebookresearch/audiocraft......
  • 当 functools.wraps() 用于泛型函数时,Mypy 1.10 报告错误
    TLDR;我有一个装饰器:更改函数签名包装的函数使用一些泛型类型参数除了我想使用的签名funtools.wraps以保留其余部分信息。有什么办法可以在不抱怨的情况下实现这一目标吗?mypy更多背景一个最小的工作示例如下所示:这......
  • 从零开始的Python开发日记(7):短信验证功能开发流程
    短信验证功能开发流程在开发一个包含登录、注册以及短信验证的功能时,你需要遵循一个系统的开发流程。以下是实现这一功能的基本步骤,包括所需的技术和代码示例。1.环境配置首先,确保你的开发环境已经配置好,并安装了必要的库和工具。pipinstallfastapiuvicornsqlalche......
  • 【Python数值分析】革命:引领【数学建模】新时代的插值与拟合前沿技术
    目录​编辑第一部分:插值的基本原理及应用1.插值的基本原理1.1插值多项式1.2拉格朗日插值 1.3牛顿插值 1.4样条插值2.插值的Python实现2.1使用NumPy进行插值2.2使用SciPy进行插值2.2.1一维插值​编辑2.2.2二维插值3.插值的应用场景3.1数据平......