Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 684
Billy Avatar asked Nov 16 '16 19:11

Billy


People also ask

Can enums have the same value Python?

By definition, the enumeration member values are unique. However, you can create different member names with the same values.

Are Python enums immutable?

Enum members should always be declared using UPPER_CASE names since they are constants. Enumerations in Python are immutable.

Can enums have the same value?

1. Two enum names can have same value. For example, in the following C program both 'Failed' and 'Freezed' have same value 0.

Do enums have to be unique?

Enum names are in global scope, they need to be unique.


1 Answers

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.

like image 102
user2357112 supports Monica Avatar answered Sep 19 '22 10:09

user2357112 supports Monica