Можно ли вызвать конструктор класса, который наследует Enum без аргументов? - PullRequest
2 голосов
/ 25 апреля 2019

У меня есть несколько классов, некоторые наследуют Enum, другие нет, и все они в конечном итоге смешиваются в большие массивы, как показано ниже:

from enum import Enum

class TestEnum(Enum):
    VAL_A = 0
    VAL_B = 1

class TestNotEnum():
    def __init__(self):
        self.var = 1

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

Вот как я бы хотел их инициализировать:

classes = [TestEnum(), TestNotEnum()]

Класс TestNotEnum не имеет проблем с ним, но TestEnum выдает следующее исключение: TypeError: __call__() missing 1 required positional argument: 'value'. Это связано с моим (плохим) использованием Enum.

Что я могу сделать, чтобы класс TestEnum все еще наследовал Enum и имел конструктор без аргументов?

Я попробовал следующее (и несколько похожих настроек):

class TestEnum(Enum):
    VAL_A = 0
    VAL_B = 1
    def __init__(self):
        super(TestEnum, self).__init__()

но я получаю только другие ошибки, такие как TypeError: __init__() takes 1 positional argument but 2 were given

Ответы [ 3 ]

1 голос
/ 25 апреля 2019

Один из вариантов, который у вас есть, - сделать так, чтобы фабричные функции назывались так же, как ваши перечисления:

from enum import Enum

class TestEnum(Enum):
    VAL_A = 0
    VAL_B = 1

def TestEnum1():
    return TestEnum

class TestNotEnum():
    def __init__(self):
        self.var = 1


instances = [TestEnum1(), TestNotEnum()]
print(instances)

Выход:

[<enum 'TestEnum'>, <__main__.TestNotEnum object at 0x03648E30>]
0 голосов
/ 23 мая 2019

Благодаря @ glibdud , который прокомментировал мой вопрос => это невозможно, как показано здесь : все классы Enum являются синглетонами, и поэтому я не могу назвать конструкцию так, как я хотелdo.

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

Другая возможностья делал свой собственный класс Enum, который соответствовал бы моим потребностям, но я решил вместо этого переделать свою архитектуру, поскольку это было быстрее: вместо того, чтобы помещать экземпляры классов таким образом classes = [TestEnum(), TestNotEnum()], я поместил ссылки classes = [TestEnum, TestNotEnum] в виде массива шаблонов и желаемых значенийво втором массиве того же размера.

Не так хорошо, как решение, которое мне бы понравилось, но оно работает и позволяет пользователю API выполнять минимальную работу, поскольку он не редактирует массивы шаблонов.

0 голосов
/ 25 апреля 2019

Поскольку это невозможно с помощью встроенного в Python класса enum, потенциальным обходным решением является использование расширенного пакета enum. Просто замените from enum import Enum на from aenum import enum as Enum, и ваш существующий код будет работать нормально.

from aenum import enum as Enum
class TestEnum(Enum):
    VAL_A = 0
    VAL_B = 1
    def __init__(self):
        super(TestEnum, self).__init__()
class TestNotEnum():
    def __init__(self):
        self.var = 1
classes = [TestEnum(), TestNotEnum()]
...