Python 中类型提示枚举成员值

Nen*_*aby 12 python enums python-3.x

对于枚举Foo,一种类型如何暗示必须包含某个枚举的成员值(而不是成员本身)的变量——例如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}
Run Code Online (Sandbox Code Playgroud)

我真的很想避免简单地打字,transaction_type因为Literal['disbursement', 'refund', 'rollback']随着时间的推移,这很容易变得不同步。

use*_*ica 12

最广泛兼容的选项是仅使用一个断言来验证文字类型不会与枚举值不同步:

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
Run Code Online (Sandbox Code Playgroud)

这确保了与静态分析器的最大兼容性,但需要重复所有成员值。此外,无法静态检查断言。


其他选项会破坏静态分析。例如,如果您使用函数式 API从文字类型创建枚举:

DisbursementValue = typing.Literal['disbursement', 'refund', 'rollback']

DisbursementType = enum.Enum('DisbursementType',
                             {name.upper(): name for name in typing.get_args(DisbursementValue)})
Run Code Online (Sandbox Code Playgroud)

那么 mypy就无法理解枚举,此时,注释就没有什么意义了。

同样,如果您尝试对类型使用非文字类型参数Literal

DisbursementValue = typing.Literal[tuple(member.value for member in DisbursementType)]
Run Code Online (Sandbox Code Playgroud)

然后那也断了