Python 3.6.5 and mypy 0.600
I wrote the code:
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
I don't understand, why I have an error 'Incompatible types in assignment ' with a variable 'arr3'. Dog is a class which inherits from a Animal. For example, I don't have an error with variable 'arr2'.
Imagine that this would be possible:
arr3: List[Animal] = arr1
Now you think you have list of animals, but this is actually a list of dogs (note that arr3
is not a copy of arr1
, they are the same list).
And because you think this is the list of animals you can add a Cat
to it.
However, because this is actually list of dogs, you cannot add a Cat
to it. Otherwise you will fail on AttributeError
after trying to use dog-specific attribute.
More generally, list is invariant - List[Animal]
cannot be assigned to List[Dog]
(because it can already contain cats) and List[Dog]
cannot be assigned to List[Animal]
(because you can add cat later)
This might not be obvious in Python, but you can make simple test:
arr3: List[Animal] = arr1
arr3.append(Cat())
for dog in arr1:
print(dog.bark())
Mypy does not allow this because this assignment might break your code logic