8

这在某种程度上是对为什么 Python 枚举中的可变值是同一个对象的后续内容?.

如果 an 的值Enum是可变的(例如lists 等),则可以随时更改这些值。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 习惯用法,这是可以的,这意味着用户可以使用可变变量作为他们的Enum值,但只是为了了解他们可能打开的蠕虫罐头。

然而,这带来了第二个问题 - 因为您可以Enum按值查找成员,并且该值可以是可变的,所以它必须通过 hashmap/ 以外的方式进行查找dict,因为可变不能是key这样的 a dict

Enum将值限制为仅不可变类型以便按值查找可以用 a 来实现不是更有效(尽管被授予,不太灵活)dict吗?

4

2 回答 2

6

我的第二个问题的答案似乎隐藏在enum.py.

每个Enum 包含 a dictof可散列value->member(即不可变)值的对,当您按值查找时,它会尝试从中检索成员。如果该值不是hashable,则它会蛮力比较所有现有值的相等性,如果找到匹配项则返回该成员。相关代码在第 468-476 行:EnumdictEnumenum.py

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希望在按值获取Enums 时进行快速查找,但仍然希望为值提供可变值的灵活性Enum(尽管我仍然想不出有人想要那个的原因首先)。

于 2016-11-17T15:08:11.220 回答
2

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

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

这与其他语言的其他枚举实体有很大的不同。然而,这个余量应该会带来一些有趣的可能性。我喜欢将字符串作为值变体,其中源代码友好的枚举名称用于源代码,而枚举值可用于表示目的,如前端代码或控制台应用程序帮助文本或其他内容。

于 2019-09-11T20:34:41.010 回答