Создание класса StringAutoEnum с чистым и кратким синтаксисом для авто-значений - PullRequest
1 голос
/ 23 октября 2019

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

Предполагая, что этот базовый StringAutoEnum класс:

import aenum

class StringAutoEnum(aenum.Enum):
    def _generate_next_value_(name, start, count, last_values):
        return name.lower()

В идеальном случае будет что-то вроде этого:

class Animal(StringAutoEnum):
    DOG, CAT, SNAKE

Таким образом, что верно следующее:

Animal.DOG.value == "dog"
Animal.CAT.value == "cat"
Animal.SNAKE.value == "snake"

Очевидно, что приведенное выше определение класса не является даже допустимым кодом Python (если DOG, CAT и SNAKE уже не были определены заранее), поэтому, если я знаю, это делается так (насколько я знаю)), вне вопроса.

Итак, я рассмотрел несколько альтернатив:

Назначение нескольким переменным:

class Animal(StringAutoEnum):
    DOG = CAT = SNAKE = auto()

Повторяемая распаковка:

class Animal(StringAutoEnum):
    DOG, CAT, SNAKE = auto()

Повторюсь, я НЕ хочу делать это:

class Animal(StringAutoEnum):
    DOG, CAT, SNAKE = auto(), auto(), auto()

И я также не хочу использовать функциональный API.

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

Проблема с повторяющейся распаковкой заключается в том, что я не могу придумать способ заранее узнать, сколько переменных находится в левой части оператора присваивания. .

Это означает, что хотя это будет работать и будет делать именно то, что я хочу:

class Auto(aenum.auto):
    def __iter__(self):
        return iter([Auto() for _ in range(3)])

class Animal(StringAutoEnum):
    DOG, CAT, SNAKE = Auto()

Это, к сожалению, не будет:

class Animal(StringAutoEnum):
    DOG, CAT, SNAKE, EMU = Auto()

И я не могу думать олюбой способ решить это таким образом для назначения произвольному количеству членов.

Может ли кто-нибудь придумать альтернативный способ решения этой проблемы, который является чистым и лаконичным? В качестве альтернативы, может кто-нибудь предложить работоспособную реализацию присваивания нескольким переменным / повторяемая распаковка, которая работает?

Заранее спасибо!

1 Ответ

1 голос
/ 23 октября 2019

Поскольку вы используете aenum, у вас есть опция AutoEnum - которая полностью охватывает магию метаклассов:

from aenum import AutoEnum

class StringAutoEnum(AutoEnum):
    #
    def _generate_next_value_(name, start, count, last_values):
        return name.lower()

class Animal(StringAutoEnum):
    DOG, CAT, SNAKE

--> list(Animal)
[<Color.Dog: 'dog'>, <Color.CAT: 'cat'>, <Color.SNAKE: 'snake'>]

Если это слишком волшебно, следующеелучшее решение - использовать auto() для каждого значения (или использовать функциональный API).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...