StrEnums 和类型缩小 (mypy)

问题描述 投票:0回答:1

我正在与 StrEnums 的类型缩小作斗争

总结我的问题,我有一些抽象基类

from abc import ABC, abstractmethod
from enum import StrEnum

class Animal(ABC):
    @staticmethod
    @abstractmethod
    def speak(animal_type: StrEnum):
        ...

以及派生类,每个类都有自己的 StrEnum:

class FrogType(StrEnum):
    frog = "frog"
    toad = "toad"

class Frog(Animal):
    @staticmethod
    def speak(animal_type: FrogType):
        print(f"{animal_type} goes ribbit")

以下代码按预期工作:


Frog.speak(FrogType.frog)  # "frog goes ribbit"

和枚举似乎兼容:

print(isinstance(FrogType.frog, FrogType))  # True
print(isinstance(FrogType.frog, StrEnum))  # True

但是 MyPy 不认为这是有效的:

# python3.11 -m mypy frog.py
frog.py:16: error: Argument 1 of "speak" is incompatible with supertype "Animal"; supertype defines the argument type as "StrEnum"  [override]
frog.py:16: note: This violates the Liskov substitution principle
frog.py:16: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#incompatible-overrides
Found 1 error in 1 file (checked 1 source file)

这似乎是一个有效的类型缩小,所以我必须注释一些错误的东西。正确的解决方案是什么?

python mypy python-typing python-3.11
1个回答
0
投票

您可以使用泛型代替

StrEnum
来避免此问题。下面定义
AnimalType
,使其具有
StrEnum
的界限:

from abc import ABC, abstractmethod
from enum import StrEnum
from typing import Generic, TypeVar

AnimalType = TypeVar("AnimalType", bound=StrEnum)
class Animal(ABC, Generic[AnimalType]):
    @staticmethod
    @abstractmethod
    def speak(animal_type: AnimalType):
        ...

class FrogType(StrEnum):
    frog = "frog"
    toad = "toad"

class Frog(Animal[FrogType]):
    @staticmethod
    def speak(animal_type: FrogType):
        print(f"{animal_type} goes ribbit")

print(isinstance(FrogType.frog, FrogType))  # True
print(isinstance(FrogType.frog, StrEnum))  # True

希望这有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.