Reputation: 136645
I want to iterate over List[A]
and List[Subclass of A]
and do the same loop. The best way I can see to do that is to concatenate the two lists. However, mypy is not happy about it.
How can I concatenate the two and keep mypy happy?
Currently, I do # type: ignore[operator]
. I would like to avoid that, if possible.
# Core Library modules
from typing import Iterable
# Third party modules
from pydantic import BaseModel
class Animal(BaseModel):
height: float
weight: float
class Cat(Animal):
lives: int = 7
cats = [Cat(height=1, weight=2, lives=7), Cat(height=3, weight=2, lives=1)]
animals = [Animal(height=9, weight=9)]
combined: Iterable[Animal] = cats + animals
for animal in combined:
print(animal)
gives
$ mypy untitled.py
untitled.py:20: error: Unsupported operand types for + ("List[Cat]" and "List[Animal]")
Found 1 error in 1 file (checked 1 source file)
Upvotes: 1
Views: 420
Reputation: 1178
If it doesn't bother you, change List
to Sequence
from typing import Sequence
class Base: pass
class Derived(Base): pass
ds: Sequence[Derived] = [Derived()]
bs: Sequence[Base] = ds
with which you'll get
$ mypy temp.py
Success: no issues found in 1 source file
Upvotes: 0
Reputation: 32233
This situation occurs because list
is invariant (provides an illustrative example).
I can offer two solutions:
List[Animal]
for successful concatenation:cats: List[Animal] = [Cat(height=1, weight=2, lives=7), Cat(height=3, weight=2, lives=1)]
animals: List[Animal] = [Animal(height=9, weight=9)]
combined: Iterable[Animal] = cats + animals
for animal in combined:
print(animal)
cats = [Cat(height=1, weight=2, lives=7), Cat(height=3, weight=2, lives=1)]
animals = [Animal(height=9, weight=9)]
for animal in itertools.chain(cats, animals):
print(animal)
Upvotes: 2