向Python枚举添加成员
我知道这不是标准用例,但我需要在Python中向向Python枚举添加成员,python,dynamic,enums,Python,Dynamic,Enums,我知道这不是标准用例,但我需要在Python中向IntEnum派生类动态添加元素。请注意,使用函数API动态创建枚举是不够的。我需要向现有枚举添加元素。我该怎么做 背景:对于那些想知道为什么会有人想这样做的人来说。我正在包装一个库,枚举的值在库中定义。我可以使用库API查询名称和值。但我无法在初始化时执行此操作,因为它依赖于库根据用户请求动态加载的组件。我可以在启动时加载所有组件,并在导入时使用函数API创建枚举,但这很耗时,而且有副作用。枚举是不可变的,这才是重点。您可以创建一个新的枚举来替换
IntEnum
派生类动态添加元素。请注意,使用函数API动态创建枚举是不够的。我需要向现有枚举添加元素。我该怎么做
背景:对于那些想知道为什么会有人想这样做的人来说。我正在包装一个库,枚举的值在库中定义。我可以使用库API查询名称和值。但我无法在初始化时执行此操作,因为它依赖于库根据用户请求动态加载的组件。我可以在启动时加载所有组件,并在导入时使用函数API创建枚举,但这很耗时,而且有副作用。枚举是不可变的,这才是重点。您可以创建一个新的枚举来替换原始枚举:
from enum import Enum
names = [m.name for m in ExistingEnum] + ['newname1', 'newname2']
ExistingEnum = Enum('ExistingEnum', names)
但是任何现有的引用(比如在其他模块中)都将继续使用旧的定义
名称可以是:
- 包含成员名称的字符串,用空格或逗号分隔。值从
start
开始递增1(可设置为关键字参数,默认为1)
- 成员名称的一个iterable(如上面的代码所示)。值从
开始
递增1
- (成员名称、值)对的可数
- 成员名称->值对的映射
这是1的extend_enum
函数的作业
一对样本Enum
s:
from aenum import Enum
class Color(Enum):
black = 0
class ColorHelp(Enum):
_init_ = 'value __doc__'
black = 0, 'the absence of color'
extend_enum
正在运行:
from aenum import extend_enum
extend_enum(Color, 'white', 1)
print Color, list(Color)
print repr(Color.black), Color.black, repr(Color.white), Color.white
print
extend_enum(ColorHelp, 'white', 1, 'the presence of every color')
print ColorHelp, list(ColorHelp)
print repr(ColorHelp.black), ColorHelp.black, ColorHelp.black.__doc__, repr(ColorHelp.white), ColorHelp.white, ColorHelp.white.__doc__
这给了我们:
<enum 'Color'> [<Color.black: 0>, <Color.white: 1>]
<Color.black: 0> Color.black <Color.white: 1> Color.white
<enum 'ColorHelp'> [<ColorHelp.black: 0>, <ColorHelp.white: 1>]
<ColorHelp.black: 0> ColorHelp.black the absence of color <ColorHelp.white: (1, 'the presence of every color')> ColorHelp.white None
[,]
颜色。黑色。白色
[, ]
ColorHelp.black缺少颜色ColorHelp.white无
1披露:我是、和库的作者。ENUM的全部要点不是不变性吗?你不能。即使是扩展现有枚举的子类也会受到保护。@MartijnPorters对这个特定用例有什么建议吗?@MightyPort是的,但是Python是一种很棒的动态粘合语言,很多时候你需要与你无法控制的东西进行交互。@Hernan:我很好奇你为什么不接受满足你需要的答案?正如我所提到的,这不是一种选择,原因与你描述的完全相同。谢谢anyway@Hernan:但是,这是使用enum
库时的唯一选项。不可变性不是枚举的“要点”。枚举的存在是为了保证有限无序集上的互斥性。在运行时将其他成员追加到现有枚举中不会违反此保证。Python的标准enum.enum
类型选择禁止此有效用例,但决不禁止第三方替代方案这样做。另请参见:可变和类型。@CecilCurry:这两个库都没有改变原始枚举,而是在现有枚举上扩展以创建新枚举。如果枚举在运行时是可变的,这将产生广泛的影响,您无法再保证处理所有可能的值(像Rust这样的语言甚至在不可在运行时可变的枚举上构建其类型安全性),第2166行,在canonical_成员中的canonical_值的扩展_枚举中。\u值:AttributeError:'MachineName'对象没有属性'values',其中MachineName是常用的python枚举。这个方法还有效吗?@likern,如果这仍然是一个问题,请。谢谢。对于任何与@likern有相同错误的人,请确保使用aenum的枚举(来自aenum导入枚举
),而不是常规枚举(来自Enum导入枚举
)。它也是可酸洗的。@Ethafurman我想更正我之前的评论。我无法加载带有扩展枚举的pickle对象。默认枚举定义不包括某些项。ValueError:不是有效的