Добавить и инициализировать переменную класса enum в Python - PullRequest
2 голосов
/ 24 июня 2019

Я реализую enum class и хочу получить сводную информацию о enum членах.Каждый enum представляет разделительную доску с разным количеством выводов, и я хочу получить максимальное количество выводов для всех плат.Мой подход состоял в том, чтобы добавить атрибут класса _max_pins, который настраивается во время __init__ каждого члена.

Проблема в том, что невозможно определить _max_pins впереди, если члены также будут становиться членами.Это не помогает определить его после членов, так как тогда члены не могут получить к нему доступ во время их __init__ Я смотрел на Объявить статическую переменную в классе enum , но таблицу можно настроить после __init__ - это было бы возможно, но после их инициализации потребуется снова отсканировать все элементы.

class IgelTyp(Enum):
    LED_1 = (24, 1)
    LED_2 = (24, 2)
    LED_3 = (16, 4)

    _max_pin = -1

    def __init__(self, pins, groups):
        if _max_pin < pins//groups:     # gives error
            _max_pin = pins//groups

    @classmethod
    def get_max_pins(cls):
        return cls._max_pin

Приведенный выше код дает UnboundLocalError: local variable '_max_pin' referenced before assignment

Когда я перемещаю назначение _max_pin передопределение члена говорит мне, что TypeError: __init__() missing 2 required positional arguments: ...

Edit 1 На самом деле, TypeError поднимается независимо от того, где я поместил назначение в классе.И когда я использую IgelTyp._max_pin = -1, я получаю NameError: name 'IgelTyp' is not defined

У кого-нибудь есть эффективное и удобочитаемое решение?

1 Ответ

2 голосов
/ 24 июня 2019

Разовое решение:

Измените __init__ для прямого доступа к словарю класса:

def __init__(self, pins, groups):
    max_pin = self.__class__.__dict__.get('max_pin', 0)
    self.__class__.max_pin = max(max_pin, pins//groups)

Интересно, что вы могли бы легко иметь каждый элемент LEDсохраните свои собственные max_pin, добавив эту строку в конце __init__:

    self.max_pin = pins//groups

так:

>>> IgelTyp.max_pin
24

но:

>>> IgelType.LED_2.max_pin
12


Решение для повторного использования

Создайте собственный дескриптор атрибута класса и используйте его, чтобы оградить max_pin от превращения в член IgelTyp:

class ClassVar:              # add (object) if using Python 2
    "a class variable"

    def __init__(self, value):
        # store initial value
        self.value = value

    def __get__(self, *args):
        # get value in ClassVar instance (only doable because all instances
        # share same value)
        return self.value

    def __set__(self, _, value):
        # save value in ClassVar instance (only doable because all instances
        # share same value)
        self.value = value

Дескрипторы, такие как property, обычно хранят значение в самом экземпляре, чтобы каждый экземпляр мог иметь свое собственное значение (например, 24, 12 и 4 из вашего примера);однако, поскольку вы хотите знать максимальное количество выводов во всех экземплярах, мы просто сохраняем это единственное значение в экземпляре ClassVar.

Изменения в IgelTyp:

class IgelTyp(Enum):

    LED_1 = (24, 1)
    LED_2 = (24, 2)
    LED_3 = (16, 4)

    max_pin = ClassVar(0)

    def __init__(self, pins, groups):
        self.max_pin = max(self.max_pin, pins//groups)

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

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