Как использовать подсказки типа для ковариантного изменяемого класса, подобного коллекции, в Python?Python

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Как использовать подсказки типа для ковариантного изменяемого класса, подобного коллекции, в Python?

Сообщение Anonymous »

Я пытаюсь создать в Python ковариантный класс, похожий на коллекцию, вот так:

Код: Выделить всё

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)
Короче говоря, мне нравится создавать подкласс Zoo, чтобы он принимал только определенный тип Animal. В данном случае DogHouse содержит только 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"
Я понимаю, о чем mypy пытается меня предупредить: следующий фрагмент синтаксически допустим, но может привести к проблеме, потому что внезапно может быть другим животным (Кот, Кенгуру, ...) в Собачьей будке (Формально код может нарушать принцип подстановки Лискова):

Код: Выделить всё

doghouse = DogHouse([])
doghouse._items.append(Cat())
Однако мой код должен позаботиться об этом, например, проверив тип в DogHouse.add(), создав Zoo._items (в некоторой степени ) приватным и сделайте большое количество копий() изменяемой последовательности, чтобы Zoo._items нельзя было изменить.
Есть ли способ сделать и то, и другое 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
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»