我对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批注检查)问题。该方法的实际实现不是此问题的主题。
问题与您在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
的子类并在代码中使用这两种类型时,请传播泛型。