Код: Выделить всё
from typing import Generic, TypeVar, List, cast
class Animal():
pass
class Dog(Animal):
pass
class Cat(Animal):
pass
class Zoo():
def __init__(self, items: List[Animal]):
self._items = items.copy() # type: List[Animal]
def add(self, animal: Animal) -> None:
self._items.append(animal)
def animal_count(self) -> int:
return len(self._items)
def get_animals(self) -> List[Animal]:
return self._items.copy()
class DogHouse(Zoo):
def __init__(self, items: List[Dog]):
self._items = items.copy() # type: List[Dog]
def add(self, dog: Dog) -> None:
assert isinstance(dog, Dog)
self._items.append(dog)
Mypy выдает две ошибки в этом коде:
Код: Выделить всё
error: Incompatible types in assignment (expression has type "List[Dog]", base class "Zoo" defined the type as "List[Animal]")
Код: Выделить всё
error: Argument 1 of "add" is incompatible with supertype "Zoo"; supertype defines the argument type as "Animal"
Код: Выделить всё
doghouse = DogHouse([])
doghouse._items.append(Cat())
Есть ли способ сделать и то, и другое DogHouse является подклассом Zoo (и извлекает выгоду из общих методов Zoo), а также использовать подсказки типов, чтобы убедиться, что мой код случайно не позволит кошкам или другим животным проникнуть внутрь. DogHouse?
Я прочитал https://mypy.readthedocs.io/en/stable/g ... f-generics, но не могу применить эти советы к своим код (исходя из языка утиного типа, такого как Python, я еще не очень многословен в отношении концепции ковариации).
Изменить: я попытался решение, определив Animal_co = TypeVar('Animal_co',bound=Animal, covariant=True), но это приводит к ошибке: невозможно использовать переменную ковариантного типа в качестве параметра. См. принятый ответ для правильный ответ и объяснение, почему это неправильно.
Подробнее здесь: https://stackoverflow.com/questions/630 ... -in-python