Понимание дисперсии типа в протоколах Python с общими типамиPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Понимание дисперсии типа в протоколах Python с общими типами

Сообщение Anonymous »

Я пытаюсь понять, как вариативность типов работает с протоколами и дженериками Python. Мои тестовые примеры, похоже, противоречат моим ожиданиям относительно инвариантного, ковариантного и контравариантного поведения.
Вот минимальный пример, демонстрирующий проблему:

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

from typing import TypeVar, Protocol

# Type variables
T = TypeVar('T')
T_co = TypeVar('T_co', covariant=True)
T_contra = TypeVar('T_contra', contravariant=True)

# Class hierarchy
class Animal: pass
class Dog(Animal): pass

# Protocols
class Feeder(Protocol[T]):
def feed(self, animal: T) -> T: ...

class Adopter(Protocol[T_co]):
def adopt(self) -> T_co: ...

class Walker(Protocol[T_contra]):
def walk(self, animal: T_contra) -> None: ...

# Implementations
class AnimalFeeder:
def feed(self, animal: Animal) -> Animal: ...

class DogFeeder:
def feed(self, animal: Dog) -> Dog: ...

class AnimalAdopter:
def adopt(self) -> Animal: ...

class DogAdopter:
def adopt(self) -> Dog: ...

class AnimalWalker:
def walk(self, animal: Animal) -> None: ...

class DogWalker:
def walk(self, animal: Dog) -> None: ...
При тестировании присвоения типов некоторые случаи ведут себя иначе, чем ожидалось:
# Test cases with expected vs actual behavior
feeder1: Feeder[Dog] = DogFeeder() # Expected ✅ Actual ✅ (exact match)
feeder2: Feeder[Dog] = AnimalFeeder() # Expected ❌ Actual ❌ (invariant)
feeder3: Feeder[Animal] = DogFeeder() # Expected ❌ Actual ✅ (Why does this work?)

adopter1: Adopter[Dog] = DogAdopter() # Expected ✅ Actual ✅ (exact match)
adopter2: Adopter[Dog] = AnimalAdopter() # Expected ❌ Actual ❌ (return type mismatch)
adopter3: Adopter[Animal] = DogAdopter() # Expected ✅ Actual ✅ (covariant, correct)

walker1: Walker[Dog] = DogWalker() # Expected ✅ Actual ✅ (exact match)
walker2: Walker[Dog] = AnimalWalker() # Expected ✅ Actual ❌ (Should work with contravariance?)
walker3: Walker[Animal] = DogWalker() # Expected ❌ Actual ✅ (Why does this work?)

< /code>
Вопросы: < /strong> < /p>

Почему проверка типа Fearder3, когда он, по-видимому, нарушает инвариантность? < /li>
Почему Walker2 терпит неудачу, когда он должен быть действительным с противодействием? Это ограничение при проверке типа Pycharm?>

Подробнее здесь: https://stackoverflow.com/questions/793 ... eric-types
Реклама
Ответить Пред. темаСлед. тема

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

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

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

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

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

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