首页 > 编程问答 >如何注释用文字初始化的“OrderedDict”的类型?

如何注释用文字初始化的“OrderedDict”的类型?

时间:2024-07-27 07:33:54浏览次数:8  
标签:python python-typing ordereddictionary pylance pyright

假设我有以下内容:

from collections import OrderedDict
from dataclasses import dataclass


@dataclass
class HelloWorld:
    x: OrderedDict[str, int]


a = OrderedDict([("a", 0), ("c", 2), ("b", 1)])
HelloWorld(a) <--- # type error here

产生的类型错误是:

Argument of type "OrderedDict[Literal['a', 'c', 'b'], Literal[0, 2, 1]]" cannot be assigned to parameter "x" of type "OrderedDict[str, int]" in function "__init__"
  "OrderedDict[Literal['a', 'c', 'b'], Literal[0, 2, 1]]" is incompatible with "OrderedDict[str, int]"
    Type parameter "_KT@OrderedDict" is invariant, but "Literal['a', 'c', 'b']" is not the same as "str"
    Type parameter "_VT@OrderedDict" is invariant, but "Literal[0, 2, 1]" is not the same as "int

奇怪的是,这个非常相似的代码片段不会产生错误:

from collections import OrderedDict
from dataclasses import dataclass


@dataclass
class HelloWorld:
    x: OrderedDict[str, int]


HelloWorld(OrderedDict([("a", 0), ("c", 2), ("b", 1)])) # <--- no error

观察到的行为与 Python 的类型提示如何在不同情况下推断类型有关。

问题根源

问题在于,当使用 a = OrderedDict([("a", 0), ("c", 2), ("b", 1)]) 初始化 a 时,mypy 会将 a 的类型推断为 OrderedDict[Literal['a', 'c', 'b'], Literal[0, 2, 1]] 。这意味着它将键和值都视为文字类型,而不是更通用的 str int

两种解决方案

  1. 使用 typing.cast 进行类型转换:
from collections import OrderedDict
from dataclasses import dataclass
from typing import cast

@dataclass
class HelloWorld:
    x: OrderedDict[str, int]


a = OrderedDict([("a", 0), ("c", 2), ("b", 1)])
HelloWorld(cast(OrderedDict[str, int], a))  # <-- 显式类型转换

在这里,我们使用 typing.cast 明确告诉 mypy 将 a 视为 OrderedDict[str, int]

  1. 在定义 OrderedDict 时提供类型提示:
from collections import OrderedDict
from dataclasses import dataclass

@dataclass
class HelloWorld:
    x: OrderedDict[str, int]


a: OrderedDict[str, int] = OrderedDict([("a", 0), ("c", 2), ("b", 1)])
HelloWorld(a)  # <-- 没有错误

在这个解决方案中,我们在定义 a 时就提供了类型提示 OrderedDict[str, int] ,这样 mypy 就不会将其推断为更严格的文字类型。

第二个代码片段为何没有错误

在的第二个代码片段中,直接将 OrderedDict([("a", 0), ("c", 2), ("b", 1)]) 传递给 HelloWorld 的构造函数。在这种情况下,mypy 可以根据 HelloWorld x 属性的类型注释 ( OrderedDict[str, int] ) 推断出 OrderedDict 的预期类型,因此不会产生错误。

总结

为了避免这种类型错误,最佳做法是在定义变量时始终提供类型提示,尤其是在使用 OrderedDict 等泛型类型时。这将有助于 mypy 正确推断类型并防止出现意外错误。

标签:python,python-typing,ordereddictionary,pylance,pyright
From: 78800160

相关文章

  • 如何在 Python 中加载站点的所有资源,包括 AJAX 请求等?
    我知道如何使用Python请求网站并读取其文本。过去,我曾尝试使用像BeautifulSoup这样的库来发出对网站上链接的所有请求,但这并没有得到看起来不像完整URL的内容,例如AJAX请求和大多数对原始域(因为“http://example.com”将丢失,更重要的是,它不是<ahref='url'>......
  • 使用Python进行PDF旋转
    使用python旋转扫描的pdf后,它工作得很好,但将pdf发送给第三方后,第三方仍然将pdf检测为90度pdf有什么办法可以解决旋转和这个问题importPyPDF2withopen('input.pdf','rb')asfile:#CreateaPDFreaderobjectreader=PyPDF2.PdfReader(file)......
  • Python win32serviceutil QueryServiceStatus:返回值是什么意思?
    我正在学习使用pywin32,并尝试在64位Python3.6.4上使用win32serviceutil模块以下代码:importwin32serviceutilasserviceserviceStatus=service.QueryServiceStatus("WinDefend")print(serviceStatus)返回以下元组:(16,4,197,0,0,0,0)我对wind......
  • Python request-html 未下载 Chromium
    importrequestsfrombs4importBeautifulSoupfromrequests_htmlimportHTMLSessionurl="https://dmarket.com/ingame-items/item-list/csgo-skins?title=recoil%20case"sesion=HTMLSession()response=sesion.get(url)response.html.render()soup=B......
  • VS Code 不改变 python 环境
    我正在使用VS-Code和anaconda环境作为python解释器。我通过ctrl+shift+`选择准确的anaconda基础环境,它也反映在vscode的下侧面板中。但是,当我检查python版本时,它显示我系统的默认python环境3.7.9如果您看到下面的截图,anaconda环境是3.......
  • 使用 Python 打开保存为 Parquet 文件中元数据的 R data.table
    使用R,我创建了一个Parquet文件,其中包含一个data.table作为主要数据,另一个data.table作为元数据。library(data.table)library(arrow)dt=data.table(x=c(1,2,3),y=c("a","b","c"))dt2=data.table(a=22222,b=45555)attr(dt,&......
  • Python 需要 Windows 长路径
    我尝试运行此安装:pip3installmsgraph-sdk它给了我这个错误:它说我需要使用此链接启用Windows长路径:https://learn.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=registry#enable-long-paths-in-windows-10-versi......
  • Python griddata() 和 Matlab griddata():某些网格点的结果不同
    在将一些(相当大的物理)Matlab代码转换为Python时,我偶然发现了这种情况。当对相同的二维离散数据进行插值时,Python/Scipy的griddata()函数给出的结果与Matlab的对应函数不同。griddata()Matlab示例代码:Python示例代码:%Samplepoints(x,y):7x5=3......
  • Ebay Python SDK 仅在特定项目类别上返回错误
    我在一个项目中使用ebaySDK一段时间了。最近我尝试导入一些商品,例如手表、手机壳等...并且我使用了eBay自己通过eBay返回的英国商店页面上的类别ID他们的“get_category_suggestions”API端点,但eBay似乎有选择地决定拒绝某些项目并引发服务器错误!为了测试,我做了......
  • 使用特定的Python版本(MacOS)制作virtualenv
    我安装了brew,python3(默认和最新版本)和pip3,pyenv。TensorFlow现在不支持python3.7,所以我听说我应该制作一个独立运行3.6或更低版本的virtualenv。我安装了python3.6.7bypyenvinstall3.6.7但无法制作virtualenv-p3.6.7(mydir)因为3.6.7不在P......