Billy Billy - 19 days ago 7
Python Question

Why are mutable values in python Enums the same object?

While experimenting with different value types for Enum members, I discovered some odd behavior when the values are mutable.

If I define the values of an Enum as different lists, the members still behave similarly to when the Enum values are typical immutable types like

str
or
int
, even though I can change the values of the members in place so that the values of the two Enum members are the same.

>>> 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


However, if I define the values to be identical lists, each member's value seems to be the same object, and thus any mutation of one member's value affects all members.

>>> 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


Why does
Enum
behave this way? Is it the intended behavior or is it a bug?

*NOTE: I'm not planning on actually using Enums this way, I was simply experimenting with using non-standard values for Enum members

Answer

From the docs:

Given two members A and B with the same value (and A defined first), B is an alias to A. By-value lookup of the value of A and B will return A. By-name lookup of B will also return 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>

This operates by equality, even when the values are mutable. Since you defined equal values for black and blue, with black first, blue is an alias for black.

Comments