在下面的代码中,
direction
数据类的Horizontal
属性被类型提示为仅允许来自Direction
枚举的5个值中的3个。我希望能够使用 from_string
静态方法从动态输入返回枚举值,如果字符串与任何枚举值都不匹配,则该方法会回退到 Direction.UNKNOWN 。实际上,代码可以工作,但 mypy
抱怨以下错误:
27:错误:赋值中的类型不兼容(表达式的类型为“Direction”,变量的类型为“Literal[Direction.LEFT,Direction.RIGHT,Direction.UNKNOWN]”)[赋值] 在 1 个文件中发现 1 个错误(检查了 1 个源文件)
这是可以理解的,因为我们从静态方法返回一个通用的
Direction
实例,而不是类型提示的特定 3 个实例之一。除了删除 mypy
方法的返回类型之外,还有什么方法可以满足 from_string
的要求吗?
from dataclasses import dataclass
from enum import auto, StrEnum
from typing import Literal
class Direction(StrEnum):
DOWN = auto()
LEFT = auto()
RIGHT = auto()
UP = auto()
UNKNOWN = auto()
@staticmethod
def from_string(value: str) -> 'Direction':
try:
return Direction(value.lower())
except ValueError:
pass
return Direction.UNKNOWN
@dataclass
class Horizontal:
direction: Literal[Direction.LEFT, Direction.RIGHT, Direction.UNKNOWN] = Direction.UNKNOWN
horizontal = Horizontal()
horizontal.direction = Direction.LEFT
print(f'{horizontal=}')
horizontal.direction = Direction.from_string(input('Enter a direction: '))
print(f'{horizontal=}')
尝试定义新的枚举作为整个枚举的子集:
from enum import auto, StrEnum
class Direction(StrEnum):
LEFT = auto()
RIGHT = auto()
UP = auto()
DOWN = auto()
UNKNOWN = auto()
Horizontal = StrEnum("Horizontal", [(Direction.LEFT.name, Direction.LEFT),
(Direction.RIGHT.name, Direction.LEFT),
(Direction.UNKNOWN.name, Direction.UNKNOWN)])
Vertical = StrEnum("Vertical", [(Direction.UP.name, Direction.UP),
(Direction.DOWN.name, Direction.DOWN),
(Direction.UNKNOWN.name, Direction.UNKNOWN)])
my_direction: Horizontal = Horizontal.LEFT
print(f'{my_direction=}')
my_direction = Horizontal[input('Enter a direction: ')]
print(f'{my_direction=}')
这将使您能够在代码中适当的地方使用子集并保持正确的输入。在这种情况下,如果用户尝试输入“向上”或“向下”,则会引发异常,我认为这就是您想要的。这是运行时检查,而不是 mypy 检查。