python - 为什么 mypy `cast` 只在某些时候起作用?
问题描述
首先我做了一个愚蠢的小班
# cheese_helpers.py
class Cheese:
pass
然后这件事发生了
# weird.py
import lxml
from typing import cast, List
import cheese_helpers
o: List[Any] = []
reveal_type(o) # builtins.List[Any] as expected
y = cast(List[cheese_helpers.Cheese], o)
reveal_type(y) # builtins.List[cheese_helpers.Cheese], as expected
# so far so good. And then:
z = cast(List[lxml.html.HtmlElement], o)
reveal_type(z) # builtins.List[Any] ???????????????
List[lxml.html.HtmlElement]
如果你问我,最后一行应该是。奶酪也没有注释,效果很好。
我确定要使最后一行正常工作,我需要获取/制作一些 lxml 注释。cast
但对我来说,我的完全被忽略似乎很奇怪。我投到奶酪类,它的工作原理。我投射到 HtmlElement 类,但它没有。
我的问题是为什么?
解决方案
您是否正在使用旧版本的 mypy?当我尝试使用 mypy 0.630(pypi 上的最新版本)和他们的 git master 分支上的最新代码对您的代码进行类型检查时,我builtins.list[Any]
在所有三种情况下都得到了一个显示的类型。
这种显示的类型希望更直观一点——问题是很遗憾 typeshed 上的库没有可用的存根,lxml
这意味着 mypy 没有关于真正内容的信息。(所有 mypy 都知道,这可能是一个类、一个函数、一个变量、一个类型别名、一个命名元组......)html.HtmlElement
所以,它放弃了,只是假设它有一个Any
.
这也解释了为什么将输出分配get_some_relevant_elements
给一个List[bool]
没有错误的作品。一个类型的变量List[Any]
理论上可以包含任何东西,包括布尔值——所以也许这是一个安全的赋值。
无论如何,如果您不喜欢这种行为,您的两个选择是:
接受
lxml
库没有类型提示/纯粹是动态类型的,并设计您的代码,以使所有动态都包含在一个位置。当您从 XML 文件中提取信息时,(可选地)验证它们并返回您自己的自定义、带注释的类。基本上,故意在代码库的动态和非动态部分之间设置障碍。为 lxml 创建自己的存根。这些存根不一定需要很复杂——只需为您需要的少数类和方法创建初步存根就足够了。(如果它们最终变得相当充实,如果你愿意的话,你也许可以开源它们并回馈社区。)
推荐阅读
- node.js - 反应页面重定向而不发送 POST 请求?
- javascript - 动态材质 DataGrid 行宽
- image-processing - 找不到函数“sqrt”的匹配重载
- google-chrome - 从 Chrome 扩展程序运行控制台命令
- python - 寻找非常大自由度系统的特征值和特征向量的方法
- spring-boot - 调用 REST API 时 GCP 中的异常
- vue.js - Vuejs日期选择器不显示任何内容
- python-3.x - Python MongoDB查询以获取'_id'!= id的文档列表
- html - 如何在不创建滚轮的情况下让 div 填充屏幕的剩余高度?
- spring-integration - Spring Integration - Java DSL 中的服务激活器