You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

问题解答

一、枚举类型的核心差异

  1. 普通Enum:
    枚举成员是Enum的实例,并非原始类型(如字符串、整数)。比如Currency.HUF是Currency类的实例,要获取实际值必须调用.value属性,不能直接和字符串"HUF"比较。
  2. IntEnum:
    继承自int和Enum,成员本质就是整数类型,能直接和整数比较(比如Status.offline == 1返回True),序列化或存入数据库时无需额外做类型转换。
  3. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 23:22:17