Why are mutable values allowed in Python Enums?

It appears the answer to my second question was hiding in plain sight in the soure code for enum.py.

Each Enum does contain a dict of value->member pairs for hashable (i.e. immutable) values, and when you look up an Enum by value, it attempts to retrieve the member from that dict. If the value is not hashable, it then brute-force compares for equality against all existing Enum values, returning the member if finds a match. The relevant code is in lines 468-476 in enum.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__))

So it appears as though the designers of enum.py wanted to have a quick lookup when getting Enums by value, but still wanted to give the flexibility of having mutable values for Enum values (even though I still can't think of a reason why someone would want that in the first place).


It's worth highlighting that enum values can be anything according to the documentation.

Note Enum member values Member values can be anything: int, str, etc.. If the exact value is unimportant you may use auto instances and an appropriate value will be chosen for you. Care must be taken if you mix auto with other values. https://docs.python.org/3/library/enum.html#creating-an-enum

It's a pretty big departure from other enum entities in other languages. The allowance should make for some interesting possibilities however. I like the string as value variant where the source code friendly enum name is used in source while the enum value can serve for presentation purposes as in front-end code or console app help text or something.