【问题标题】:How to use mypy annotation in a for loop with generic subclassing / inheritance?如何在具有通用子类化/继承的 for 循环中使用 mypy 注释?
【发布时间】:2020-05-05 15:41:42
【问题描述】:

我被 python mypy 继承和 for 循环困住了。

为了简化,这里是一个有效的 stubs/xml/__init__.pyi 存根:

from typing import Dict,Iterable,Sized,Iterator,List,Optional, TypeVar

T = TypeVar('T', bound='Element')


class Element():
    attrib: Dict[str,str]

    def getchildren(self)->List[T]:...
    def getparent(self)->List[Element]:...
    def drop(self)->None:...

这是 stubs/xml/html/__init__.pyi 中子元素的有效存根

from typing import Sized,Dict,Type,Generic
from xml import Element
import xml

class HtmlElement(xml.Element):...

这是我无法更正的代码:最后一个例子是让 mypy 抱怨,这是一个安静的问题

from typing import List, Dict, Set, Optional, Tuple

from xml.html import HtmlElement
from xml import Element
import xml
import xml.html

a: HtmlElement = HtmlElement()
b: HtmlElement = HtmlElement()

# getparent return ->List[Element]
d: List[Element] = a.getparent()
for d_element in d:
    d_element.drop() # Mypy is ok

for f_element in b.getparent():
    f_element.drop() # Mypy is ok

# getchildren return ->List[T] 
c: List[HtmlElement] = a.getchildren()
for a_element in c:
    a_element.drop()  #Mypy is ok

b_element: HtmlElement # requested by mypy 'Need type annotation for 'b_element'
for b_element in b.getchildren():
    b_element.drop() # Mypy is complaining with : <nothing> has no attribute "drop"

当 type 是泛型时,Mypy 似乎不理解预输入,而它在所有其他情况下都有效。

如何在这个 for 循环中使用 mypy 注释和泛型子类化/继承?这是一个 mypy 错误,还是我错过了什么?

请注意,这是一个 Mypy(即 Python 注释检查)问题。方法的真正实现不是这个问题的主题。

【问题讨论】:

  • 可能是HTMLElement 的问题。类似这样的工作:b_element: HtmlElement = HtmlElement()
  • 能否确定在HtmlElement类中实现了drop方法?
  • @keval,这与实施无关。 Mypy 是关于注释 Python 并具有类似错误的“编译”。所以我的问题是关于 Mypy 错误

标签: python stub mypy


【解决方案1】:

问题与您在Element 中对getchildren 的定义有关。

该函数被注释为返回一些通用的 TypeVar——但是 TypeVar 到底是什么? mypy 不可能推断出 T 应该在那里。一个元素? Element 的某个子类?

您应该完全停止使用 TypeVars 并让它返回 List[Element] 或使 Element 类通用。

from typing import Generic, TypeVar, Dict, List

T = TypeVar('T', bound='Element')

class Element(Generic[T]):
    attrib: Dict[str,str]

    def getchildren(self) -> List[T]: ...
    def getparent(self) -> List[Element]: ...
    def drop(self) -> None: ...

如果我们将类型提示添加回我们通常省略的self 参数,这意味着我们已经将getchildren 的签名从def getchildren(self: Element) -&gt; List[T] 转换为def getchildren(self: Element[T]) -&gt; List[T]。后一个签名满足您必须始终在您编写的所有函数和方法签名中至少使用两次 TypeVar 的规则。

当然,当您继承 HTMLElement 并在代码中使用任一类型时,传播泛型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-29
    • 2015-10-01
    • 2020-03-23
    • 1970-01-01
    • 2019-01-09
    • 2021-02-03
    • 1970-01-01
    相关资源
    最近更新 更多