мипы проблемы с наследованием объектов в списках - PullRequest
0 голосов
/ 12 мая 2018

Python 3.6.5 и mypy 0.600

Я написал код:

from typing import List


class Animal():
    pass


class Dog(Animal):
    def __init__(self) -> None:
        super()

    def bark(self) -> None:
        pass


class Cat(Animal):
    def __init__(self) -> None:
        super()

    def meow(self) -> None:
        pass


arr1: List[Dog] = [Dog(), Dog()]
arr2: List[Animal] = [Dog(), Dog()]

# error: Incompatible types in assignment (expression has type "List[Dog]", variable has type "List[Animal]")
arr3: List[Animal] = arr1

Не понимаю, почему у меня ошибка «Несовместимые типы в присваивании» с переменной «arr3». Собака - это класс, который наследуется от животного. Например, у меня нет ошибки с переменной 'arr2'.

1 Ответ

0 голосов
/ 12 мая 2018

Представьте, что это возможно:

arr3: List[Animal] = arr1

Теперь вы думаете, что у вас есть список животных, но на самом деле это список собак (обратите внимание, что arr3 не является копией arr1, они тот же список ).

И поскольку вы думаете, что это список животных, вы можете добавить к нему Cat.

Однако, поскольку это фактически список собак, вы не можете добавить к нему Cat.В противном случае вы потерпите неудачу на AttributeError после попытки использовать атрибут, специфичный для собаки.

В общем, список инвариантен - List[Animal] нельзя назначить List[Dog] (потому что он уже может содержать кошек) и List[Dog] нельзя присвоить List[Animal] (потому что вы можете добавить cat позже)


Это может быть неочевидно в Python, но вы можете сделать простой тест:

arr3: List[Animal] = arr1 
arr3.append(Cat())
for dog in arr1:
    print(dog.bark())

Mypy не позволяет этого, потому что это назначение может нарушить вашу логику кода

...