在为Enum
成员尝试不同的值类型时,我发现当值是可变的时会出现一些奇怪的行为。
如果我将Enum
的值定义为不同的列表,则成员的行为仍然类似于Enum
值是str
或int
等典型不可变类型的时间,即使我可以更改成员的值,以便两个Enum
成员的值相同:
>>> class Color(enum.Enum):
black = [1,2]
blue = [1,2,3]
>>> Color.blue is Color.black
False
>>> Color.black == Color.blue
False
>>> Color.black.value.append(3)
>>> Color.black
<Color.black: [1, 2, 3]>
>>> Color.blue
<Color.blue: [1, 2, 3]>
>>> Color.blue == Color.black
False
>>> Color.black.value == Color.blue.value
True
但是,如果我将值定义为相同的列表,则每个成员的值似乎都是相同的对象,因此一个成员的值的任何突变都会影响所有成员:
>>> class Color(enum.Enum):
black = [1,2,3]
blue = [1,2,3]
>>> Color.blue is Color.black
True
>>> Color.black == Color.blue
True
>>> Color.black.value.append(4)
>>> Color.black
<Color.black: [1, 2, 3, 4]>
>>> Color.blue
<Color.black: [1, 2, 3, 4]>
>>> Color.blue == Color.black
True
Enum
为何如此表现?这是预期的行为还是一个错误?
注意: 我不打算以这种方式实际使用Enums,我只是尝试使用Enum成员的非标准值
答案 0 :(得分:10)
来自docs:
给定两个成员A和B具有相同的值(并且A定义为第一个),B是A的别名.A和B的值的值按字母顺序查找将返回A.B的名字查找也将返回A:
>>> class Shape(Enum): ... square = 2 ... diamond = 1 ... circle = 3 ... alias_for_square = 2 ... >>> Shape.square <Shape.square: 2> >>> Shape.alias_for_square <Shape.square: 2> >>> Shape(2) <Shape.square: 2>
即使价值是可变的,这也是平等运作的。由于您为black
和blue
定义了相同的值,而black
首先为blue
,black
是{{1}}的别名。
答案 1 :(得分:5)
要补充@user2357112's answer,请查看EnumMeta
,所有Enum
类的元类;它可以查看具有类型的每个类定义,并进行更改以更改它。
具体来说,它通过简单的分配来处理re-assign members with the same value in its __new__
method:
# If another member with the same value was already defined, the
# new member becomes an alias to the existing one.
for name, canonical_member in enum_class._member_map_.items():
if canonical_member._value_ == enum_member._value_:
enum_member = canonical_member
break
我没有选择检查文档,而是查看了源代码。要接受的课程:始终检查文档,以及是否提出ExplanationNotFound
;检查来源: - )
答案 2 :(得分:3)
Python 3 Enum类不会强制执行唯一性,除非您通过unique decorator
明确说明它另见duplicate values。由于blue
与black
相同,因此它只会成为black
的别名。
答案 3 :(得分:3)
From the Python documentation for Enums:
默认情况下,枚举允许多个名称作为相同值的别名。如果不需要这种行为,可以使用以下装饰器来确保每个值在枚举中只使用一次....
这意味着blue
是black
的别名。当任何一个改变时,另一个也必须改变。
但是,您可以使用enum.unique
装饰器强制Python使每个枚举值唯一。同样来自文档:
>>> from enum import Enum, unique >>> @unique ... class Mistake(Enum): ... one = 1 ... two = 2 ... three = 3 ... four = 3 ... Traceback (most recent call last): ... ValueError: duplicate values found in <enum 'Mistake'>: four -> three