假设我有课:
from typing import Literal
class Computer:
def __init__(self, operation: Literal['floor', 'ceil', 'square']):
if operation not in ('floor', 'ceil', 'square'):
raise ValueError(f'Invalid operation "{operation}"')
self._operation = operation
# ... lots of methods that use `self._operation`, e.g.
def is_much_larger(self, value: float) -> bool:
if self._operation == 'square':
if value > 1:
return True
else:
return False
else:
return False
我想将可行值列表(即
'floor', 'ceil', 'square'
)保留在一个地方。有什么好的食谱吗?
MyPy docs 通过
assert_never
的建议展示了一些想法,但这只是 MyPy 在运行时之前给出错误,而不是作为维护单个值列表的方法。
您可以使用输入模块内省这些参数。
>>> import typing
>>> Operation = typing.Literal['floor', 'ceil', 'square']
>>> typing.get_args(Operation)
('floor', 'ceil', 'square')
您可以使用类型别名,然后使用
typing.get_args
获取所需的值,例如:
import typing
# in Python >= 3.10 , use explicit type alias:
# Operation: typing.TypeAlias = typing.Literal['floor', 'ceil', 'square'
Operation = typing.Literal['floor', 'ceil', 'square']
class Computer:
def __init__(self, operation: Operation:
if operation not in typing.get_args(Operation):
raise ValueError(f'Invalid operation "{operation}"')
self._operation = operation
# ... lots of methods that use `self._operation`, e.g.
def is_much_larger(self, value: float) -> bool:
if self._operation == 'square':
if value > 1:
return True
else:
return False
else:
return False
另一种方法是使用
Enum
。
这将所有选项封装在一起并极大地简化了类型提示。但是,这意味着每当您调用该函数时都必须使用此
Enum
。如果你有很多功能并且有很多不同的Enums
,这会有点烦人。
from enum import Enum, auto
class Operation(Enum):
# All caps by convention
FLOOR = auto()
CEIL = auto()
SQUARE = auto()
class Computer:
# Type hint is much simpler, especially if there are many options
def __init__(self, operation: Operation):
# No need for ValueError check
self._operation = operation
def is_much_larger(self, value: float) -> bool:
# Example usage, always have to compare to Operation.SOMETHING
if self._operation == Operation.SQUARE:
return value > 1
return False
注意:
auto()
自动为每个成员分配唯一的int值(即1、2、3...)