Python枚举类型差异解析及Tortoise ORM适配疑问
Tortoise ORM枚举字段疑问与枚举类型解析
现象说明
我在研究Tortoise ORM的字段时发现:
CharEnumField支持两种字符串枚举写法:
文档示例是同时继承str和Enum的类:
但移除class Currency(str, Enum): HUF = "HUF" EUR = "EUR" USD = "USD"str,只继承Enum的写法也能正常运行:class Currency(Enum): HUF = "HUF" EUR = "EUR" USD = "USD"IntEnumField却必须使用IntEnum,用普通Enum会报错:
文档要求的写法:class Status(IntEnum): offline = 1 online = 2 unknown = 3
我的疑问
- 这些枚举类型到底有什么差异?
- 为什么有
IntEnum却曾经没有StrEnum? - 为什么不能只用普通
Enum满足所有场景需求?
复现模型代码
class User(Model): id = BigIntField(primary_key=True) currency = CharEnumField(Currency, default=Currency.USD) test = IntEnumField(Status, default=Status.unknown)
问题解答
一、枚举类型的核心差异
- 普通
Enum:
枚举成员是Enum的实例,并非原始类型(如字符串、整数)。比如Currency.HUF是Currency类的实例,要获取实际值必须调用.value属性,不能直接和字符串"HUF"比较。 IntEnum:
继承自int和Enum,成员本质就是整数类型,能直接和整数比较(比如Status.offline == 1返回True),序列化或存入数据库时无需额外做类型转换。str+Enum(或Python3.11+的StrEnum):
成员既是Enum实例也是字符串类型,能直接和字符串比较(Currency.HUF == "HUF"返回True),是Python3.11版本之前实现字符串枚举的标准写法。
二、为什么两个枚举字段的兼容情况不同?
CharEnumField:内部会自动提取枚举成员的.value属性作为字符串存储,不管你用的是str+Enum还是普通Enum,只要成员值是字符串,就能正确处理,所以两种写法都能运行。IntEnumField:设计时期望枚举成员能直接被当作整数处理(因为数据库存储的是整数类型),普通Enum的成员是实例,无法直接转换为整数,而IntEnum成员本身就是整数,能直接适配字段的类型要求,所以必须用IntEnum。
三、为什么有IntEnum却曾没有StrEnum?
Python的enum模块在3.4版本引入时就包含了IntEnum,但StrEnum是直到3.11版本才正式加入标准库。在这之前,开发者普遍用str+Enum的方式实现字符串枚举,所以Tortoise ORM的文档也采用了这种兼容旧版本的写法。
四、为什么不能只用普通Enum?
普通Enum的成员是独立的实例类型,和原始类型(int、str)不兼容,在数据库映射、序列化这类需要和原始类型交互的场景中,必须手动处理.value的提取,增加了额外的代码成本。而IntEnum/StrEnum兼顾了枚举的语义和原始类型的特性,在这类场景下更便捷。
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

