Может ли кто-нибудь помочь объяснить проблему mypy в Python с несовместимым типом возвращаемого значения из-за ковариациPython

Программы на Python
Ответить
Anonymous
 Может ли кто-нибудь помочь объяснить проблему mypy в Python с несовместимым типом возвращаемого значения из-за ковариаци

Сообщение Anonymous »

Извиняюсь, если уже есть прямой ответ, но я слишком глуп, чтобы его увидеть. Я работаю с Python 3.13+ и Mypy 1.91.1. Я прочитал документацию mypy, прочитал здесь несколько похожих вопросов/ответов и провел часы с искусственным интеллектом.
Я пытаюсь написать декодер JSON на Python, используя функциональное программирование, которое возвращает общий результат, а не выдает ошибки. Я считаю, что проблема связана с тем, что mypy думает, что базовая структура данных может в какой-то момент измениться в будущем, и использование «коварианта» устраняет проблему, но mypy жалуется на то, что ковариант является параметром.
Может ли кто-нибудь взглянуть на следующий код и ошибку mypy и объяснить, почему это происходит, как можно проще, и как я могу изменить код, чтобы устранить ошибки, сохраняя при этом неизменяемые классы данных?

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

from dataclasses import dataclass
from typing import Literal

@dataclass(frozen=True)
class Ok[T]:
value: T

@dataclass(frozen=True)
class Err[E]:
value: E

type Result[T, E] = Ok[T] | Err[E]

@dataclass(frozen=True)
class Dog:
nm: str
kind: Literal['Dog'] = 'Dog'

@dataclass(frozen=True)
class Cat:
nm: str
kind: Literal['Cat'] = 'Cat'

type Animal = Dog | Cat

def decodeDog(slop: dict) -> Result[Dog, str]:
try:
return Ok(Dog(slop["nm"]))
except Exception as e:
return Err(f"Decode Error: {e}")

def decodeCat(slop: dict) -> Result[Cat, str]:
try:
return Ok(Cat(slop["nm"]))
except Exception as e:
return Err(f"Decode Error: {e}")

def decodeAnimal(slop: dict) -> Result[Animal, str]:
match slop.get("kind"):
case "Dog":
return decodeDog(slop)
case "Cat":
return decodeCat(slop)
case _:
return Err("Unknown Animal")

if __name__ == "__main__":
print(decodeDog({"nm": "Spot"}))
print(decodeDog({"someOtherField": "someOtherStuff"}))
print(decodeCat({"nm": "Garfield"}))
print(decodeCat({"someOtherField": "someOtherStuff"}))
print(decodeAnimal({"nm": "Spot", "kind": "Dog"}))
print(decodeAnimal({"nm": "Garfield", "kind": "Cat"}))
print(decodeAnimal({"nm": "ET", "kind": "Animal"}))
Код работает нормально

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

❯ python example.py
Ok(value=Dog(nm='Spot', kind='Dog'))
Err(value="Decode Error: 'nm'")
Ok(value=Cat(nm='Garfield', kind='Cat'))
Err(value="Decode Error: 'nm'")
Ok(value=Dog(nm='Spot', kind='Dog'))
Ok(value=Cat(nm='Garfield', kind='Cat'))
Err(value='Unknown Animal')
но мой пи недоволен

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

example.py:42: error: Incompatible return value type (got "Ok[Dog] | Err[str]", expected "Ok[Dog | Cat] | Err[str]")  [return-value]
example.py:44: error: Incompatible return value type (got "Ok[Cat] | Err[str]", expected "Ok[Dog | Cat] | Err[str]")  [return-value]
Большое спасибо!

Подробнее здесь: https://stackoverflow.com/questions/798 ... value-type
Ответить

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

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

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

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

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