如何在具有通用子类化/继承的for循环中使用mypy注释?

问题描述 投票:0回答:1

我对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"

Mypy似乎不理解预类型,当类型是通用的,并且在所有其他情况下都可以使用时。

如何在带有通用子类化/继承的for循环中使用mypy注释?那是mypy的错误,还是我缺少什么?

请注意,这是一个Mypy(即Python批注检查)问题。该方法的实际实现不是此问题的主题。

python stub mypy
1个回答
0
投票

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

该函数被注释为返回一些通用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) -> List[T]转换为def getchildren(self: Element[T]) -> List[T]。后一个签名满足以下规则:在编写的所有函数和方法签名中,您必须始终至少使用TypeVar两次。]

当然,当您继承HTMLElement的子类并在代码中使用这两种类型时,请传播泛型。

© www.soinside.com 2019 - 2024. All rights reserved.