python - 在 Python 中键入提示枚举成员值
问题描述
对于 enum Foo
,一种类型如何提示必须包含某个 Enum 的成员值(而不是成员本身)的变量 - 例如,一个Foo(x)
将返回的有效成员的值Foo
?
这是我的激励示例的简化版本:
class DisbursementType(Enum):
DISBURSEMENT = "disbursement"
REFUND = "refund"
ROLLBACK = "rollback"
class SerializedDisbursement(TypedDict):
transaction_type: ???
id: str
amount: float
a: SerializedDisbursement = {"transaction_type": "refund", id: 1, amount: 4400.24}
我真的很想避免简单地输入transaction_type
,因为Literal['disbursement', 'refund', 'rollback']
随着时间的推移很容易失去同步。
解决方案
最广泛兼容的选项是只有一个断言来验证文字类型不会与枚举值不同步:
class DisbursementType(enum.Enum):
DISBURSEMENT = "disbursement"
REFUND = "refund"
ROLLBACK = "rollback"
DisbursementValue = typing.Literal['disbursement', 'refund', 'rollback']
assert set(typing.get_args(DisbursementValue)) == {member.value for member in DisbursementType}
class SerializedDisbursement(typing.TypedDict):
transaction_type: DisbursementValue
id: str
amount: float
这确保了与静态分析器的最大兼容性,但需要重复所有成员值。此外,不能静态检查断言。
其他选项会破坏静态分析。例如,如果您使用函数式 API从文字类型创建枚举:
DisbursementValue = typing.Literal['disbursement', 'refund', 'rollback']
DisbursementType = enum.Enum('DisbursementType',
{name.upper(): name for name in typing.get_args(DisbursementValue)})
那么 mypy不理解枚举,并且在这一点上,根本没有注释。
同样,如果您尝试对类型使用非文字类型参数Literal
:
DisbursementValue = typing.Literal[tuple(member.value for member in DisbursementType)]
然后也打破了。