为什么Python Enums中允许使用可变值?

时间:2016-11-17 14:57:49

标签: python python-3.x dictionary enums hashable

这有点跟随Why are mutable values in Python Enums the same object?

如果Enum的值是可变的(例如list s等),则可以随时更改这些值。如果Enum成员按值检索,我认为这会带来一些问题,特别是如果有人无意中更改了Enum他查找的值:

>>> from enum import Enum
>>> class Color(Enum):
        black = [1,2]
        blue = [1,2,3]

>>> val_1 = [1,2]
>>> val_2 = [1,2,3]
>>> Color(val_1)
<Color.black: [1, 2]>
>>> Color(val_2)
<Color.blue: [1, 2, 3]>
>>> my_color = Color(val_1)
>>> my_color.value.append(3)
>>> Color(val_2)
<Color.black: [1, 2, 3]>
>>> Color(val_1)
Traceback (most recent call last):
  ...
ValueError: [1, 2] is not a valid Color

我认为正常的Python习语是好的,暗示用户可以使用mutable作为Enum值,但只是为了理解他们可能正在打开虫子。

然而,这会引发第二个问题 - 因为你可以按值查找Enum memeber,并且值可以是可变的,它必须通过hashmap / {{1以外的方式进行查找因为mutable不能是dict中的key

dict值限制为仅可变类型以使Enum可以实现按值查找更有效(虽然,授予,不太灵活)?

2 个答案:

答案 0 :(得分:2)

似乎我的第二个问题的答案隐藏在enum.py的原始代码中。

每个Enum 包含dict value->member hashable (即不可变)值的对,当你看按值增加Enum,它会尝试从dict检索成员。如果该值不是 hashable ,那么它会将brute-force与所有现有Enum值进行相等性比较,如果找到匹配则返回成员。相关代码位于enum.py

中的第468-476行
try:
    if value in cls._value2member_map_:
        return cls._value2member_map_[value]
except TypeError:
    # not there, now do long search -- O(n) behavior
    for member in cls._member_map_.values():
        if member._value_ == value:
            return member
raise ValueError("%r is not a valid %s" % (value, cls.__name__))

所以好像enum.py的设计师想要在按值获取Enum时快速查找,但仍希望为Enum提供可变值的灵活性价值观(尽管我仍然无法想到一个原因为什么有人会首先想要这个)。

答案 1 :(得分:2)

值得强调的是,根据文档,枚举值可以是任何

  

注意Enum成员值成员值可以是任何值:int,str等。   如果确切值不重要,则可以使用自动实例和   将会为您选择适当的值。如果您要小心   将auto与其他值混合。   https://docs.python.org/3/library/enum.html#creating-an-enum

与其他语言的枚举实体有很大的不同。但是,津贴应为一些有趣的可能性提供条件。我喜欢将字符串作为值变体,其中在源代码中使用源代码友好的枚举名称,而枚举值可用于表示目的,如前端代码或控制台应用程序帮助文本或其他内容。