Добавление свойства в Enum - PullRequest
       40

Добавление свойства в Enum

2 голосов
/ 26 января 2020

Я хотел бы иметь Enum с внутренним свойством для каждого значения перечисления, это свойство не может быть установлено или инициализировано пользователем, но как только пользователь создал Enum из значения, он сможет чтобы прочитать (получить) это внутреннее свойство на основе значения.

например,

class Channels(Enum):

    Email     = 1, True   # True is the value of the internal property for value 1
    Sms       = 2, True   # True is the value of the internal property for value 1
    Log       = 3, False  # False is the value of the internal property for value 1

Проблема в том, что в настоящее время для создания экземпляра этого класса мне нужно: x = Channels((1, True)) и плохо. Я хочу иметь возможность создавать экземпляры, такие как: x = Channels(1) (т.е. True является внутренним свойством 1, оно не должно быть указано пользователем).

Моя вторая попытка была:

class Channels2(Enum):

    @DynamicClassAttribute
    def internal_property(self):
        if self.value == 1:
            return True
        elif self.value == 2:
            return True
        elif self.value == 3:
            return False


    Email     = 1
    Sms       = 2
    Log       = 3

И, похоже, это работает (x = Channels(1) работает, а x.internal_property возвращает True, как и должно быть).

Проблема здесь в том, что это не так эффективно, выполнять эти операторы if каждый раз при обращении к internal_property. Есть ли другой способ заставить Enum рассматривать internal_property как дополнительное поле экземпляра (поверх Enum normal name и value поля)?

Ответы [ 2 ]

3 голосов
/ 26 января 2020

Вы можете использовать __new__() как , задокументированное здесь , чтобы настроить значение объекта enum. Например, вы можете использовать ваши оригинальные определения, такие как:

from enum import Enum

class Channels(Enum):

    def __new__(cls, value, internal_property):
        obj = object.__new__(cls)
        obj._value_ = value
        obj.internal_property = internal_property
        return obj

    email = 1, True
    sms   = 2, True
    log   = 3, False

print(Channels.email)
# Coordinate.email

print(Channels.email.value)
# 1

print(Channels(3))
# Coordinate.log

print(Channels(3).internal_property)
# False

print(Channels(1).internal_property)
#True
1 голос
/ 26 января 2020

@ MarkMeyer хорошо подходит для решения stdlib, но если вы ищете более простые способы создания Enum s, вам следует попробовать aenum 1 :

from aenum import Enum

class Channels(Enum):
    #
    _init_ = 'value internal_property'
    #
    email = 1, True
    sms   = 2, True
    log   = 3, False

и используется:

>>> list(Channels)
[<Channels.email: 1>, <Channels.sms: 2>, <Channels.log: 3>]

>>> Channels(2)
<Channels.sms: 2>

>>> Channels(2).name
'sms'

>>> Channels(2).internal_property
True

1 Раскрытие информации: я являюсь автором Python stdlib Enum, enum34 backport и расширенное перечисление (aenum) .

...