Как использовать аннотацию mypy в a для l oop с наследованием / наследованием generi c? - PullRequest
0 голосов
/ 19 января 2020

Я застрял с python наследованием mypy и для l oop.

Для упрощения приведу действительную заглушку для заглушек / 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:...

Вот верная заглушка для элемента son в stubs / xml / html / __ init __. Pyi

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

class HtmlElement(xml.Element):...

Вот код, который я не могу исправить: последний пример заставляет mypy жаловаться, что тихо problemmati c

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 не понимает предварительную типизацию, когда тип является обобщенным c, когда он работает во всех других случаях.

Как использовать аннотацию mypy в этом для l oop с наследованием / наследованием generi c? Это ошибка mypy или я что-то упустил?

Обратите внимание, что это вопрос Mypy (ie, Python проверка аннотаций). Реальная реализация метода не является предметом этого вопроса.

1 Ответ

0 голосов
/ 20 января 2020

Проблема связана с вашим определением getchildren в Element.

Эта функция аннотирована так, чтобы возвращать некоторый обобщенный c TypeVar - но TypeVar чего именно? Mypy не может сделать вывод, что там должно быть. Элемент? Какой-то подкласс Element?

Вы должны либо полностью прекратить использование TypeVars и вернуть List[Element], либо сделать класс Element generi c.

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 как минимум дважды во всех сигнатурах функций и методов, которые вы пишете.

И, конечно, распространяйте обобщенный c, когда вы подкласс HTMLElement, и используйте либо введите свой код.

...