代码之家  ›  专栏  ›  技术社区  ›  Sheena

为什么mypy'cast'只在某些时候起作用?

  •  2
  • Sheena  · 技术社区  · 6 年前

    首先我上了一节愚蠢的小班

    # 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

    我的问题是为什么?

    1 回复  |  直到 6 年前
        1
  •  0
  •   Michael0x2a    6 年前

    您是否使用了旧版本的mypy?当我尝试用mypy0.630(pypi上的最新版本)和git主分支上的最新代码对代码进行类型检查时,我发现了 builtins.list[Any] 在这三种情况下。

    这个显示的类型希望更直观一点——问题是不幸的是,没有可用的存根 lxml 上的库 typeshed ,这意味着mypy没有关于 html.HtmlElement

    所以,它放弃了,只是假设它有一种 Any .

    get_some_relevant_elements List[bool] 工作正常。类型的变量 List[Any] 理论上可以包含任何东西,包括胸部——所以 这是个安全的任务。


    在任何情况下,如果您不喜欢这种行为,您的两个选择是:

    1. 接受 库没有类型提示/是纯动态类型的,请设计代码,使所有动态都包含在一个位置中。当您从XML文件中提取信息时,(可选地)验证它们并返回您自己的自定义、带注释的类。基本上,故意在代码库的动态和非动态部分之间包含一个屏障。

    2. 为lxml创建自己的存根。这些存根不一定很复杂——只需为所需的几个类和方法创建初步存根就足够了(如果他们最终变得相当充实,你可以把他们开源,如果你愿意的话,还可以回馈社区。)