Python enum.Enum создает псевдоним вместо нового значения - PullRequest
0 голосов
/ 26 июня 2018

Я только что заметил очень странное поведение Enum + defaultdict в pyhton. Я определяю перечисление как это, которое собирает некоторые словари по умолчанию:

from enum import Enum
from collections import defaultdict

class A(Enum):
     a = defaultdict(lambda: 1)
     b = defaultdict(lambda: 2)

Затем, когда я смотрю на то, что внутри А:

In [11]: A.a
Out[11]: <A.a: defaultdict(<function A.<lambda> at 0x7f773f03b510>, {})>

In [12]: A.b
Out[12]: <A.a: defaultdict(<function A.<lambda> at 0x7f773f03b510>, {})>

Так что A.b это просто псевдоним A.a. Для меня это очень похоже на ошибку, даже если за этим, вероятно, есть веская причина. Есть идеи?

Добавление

Так как это появилось в комментариях, заметка о том, почему кто-то хотел бы поместить дикт в Enum. Я считаю, что очень часто полезно группировать константы в пространства имен, чтобы можно было получить доступ к значениям как A.a.constant1, A.b.constant1 и т. Д. В настоящее время при попытке сделать это с помощью Enums возникает значение AttributeError. Конечно, можно сделать что-то вроде:

class A:
    class a(Enum):
        constant1 = 1
    class b(Enum):
        constant1 = 2

Однако это не позволяет использовать возможности Enum (итерация, доступ через __getitem__ и т. Д.).

1 Ответ

0 голосов
/ 26 июня 2018

Если вы присваиваете двум элементам перечисления равные значения, enum создаст один элемент перечисления с двумя псевдонимами, а не с двумя различными элементами.

Defaultdicts наследуют сравнение равенства от dict. Это означает, что фабрика по умолчанию не является частью == сравнений. Ваши члены перечисления имеют равные значения, поэтому они объединяются.

Использование изменяемых объектов в качестве значений перечисления обычно является плохой идеей. Они имеют тенденцию нарушать enum конструктивные предположения типа «равенство ценностей не меняется». Подумайте о том, чтобы присоединить эти defaultdicts к членам enum каким-либо другим способом.

...