如何从整数创建Python enum.Flag实例:未定义位映射至INVALID
自定义Flag枚举:将未定义位映射为INVALID
问题描述
现有如下Flag枚举:
from enum import Flag class MyFlags(Flag): FLAG0 = 0x01 FLAG1 = 0x02 #INVALID = 0x04 FLAG3 = 0x08 #INVALID = 0x10 #INVALID = 0x20 #INVALID = 0x40 INVALID = 0x80
需要实现:从整数创建MyFlags实例时,若整数包含的2的幂位未在枚举中定义,这些位将被替换为MyFlags.INVALID。示例效果如下:
>>> MyFlags(0x01), MyFlags(0x03), MyFlags(0x04), MyFlags(0x85) (<MyFlags.FLAG0: 1>, <MyFlags.FLAG0|FLAG1: 3>, <MyFlags.INVALID: 128>, <MyFlags.FLAG0|INVALID: 129>)
同时要支持快速判断是否存在无效标志:
>>> rx_byte = 0x81 >>> MyFlags.INVALID in MyFlags(rx_byte) True
解决方案
通过重写枚举类的__call__方法,实现自定义的整数转换逻辑:
from enum import Flag class MyFlags(Flag): FLAG0 = 0x01 FLAG1 = 0x02 #INVALID = 0x04 FLAG3 = 0x08 #INVALID = 0x10 #INVALID = 0x20 #INVALID = 0x40 INVALID = 0x80 @classmethod def __call__(cls, value): # 计算所有有效标志的位掩码(排除INVALID) valid_mask = sum(f.value for f in cls if f != cls.INVALID) # 提取输入值中的有效位部分 valid_part = value & valid_mask # 检查是否存在未定义的位,若有则添加INVALID标记 if value & ~valid_mask != 0: valid_part |= cls.INVALID.value # 调用父类方法创建最终实例 return super().__call__(valid_part)
原理说明
- 有效掩码计算:枚举所有非
INVALID的成员,求和得到有效位掩码,用于筛选输入值中的合法位。 - 有效位提取:输入值与有效掩码按位与,保留所有合法标志位。
- 无效位处理:若输入值存在有效掩码外的位(未定义的2的幂位),则将
INVALID位合并到结果中。 - 实例生成:将处理后的数值传入父类方法,生成符合要求的
MyFlags实例。
内容的提问来源于stack exchange,提问作者Betheev
相关产品推荐
相关产品推荐

