Добавлять атрибуты Enum динамически - PullRequest
1 голос
/ 10 апреля 2020

Во-первых, я знаю, что Enum в Python неизменны.

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

class SalesFilter(str, enum.Enum):
    this_month = 'this_month'
    last_month = 'last_month'

    this_year = 'this_year'
    last_year = 'last_year'

    jan = 'jan'
    feb = 'feb'
    mar = 'mar'
    apr = 'apr'
    may = 'may'
    jun = 'jun'
    jul = 'jul'
    aug = 'aug'
    sep = 'sep'
    oct = 'oct'
    nov = 'nov'
    dec = 'dec'

Интересно, есть ли способ генерировать эти месяцы динамически, я хотел бы сделать что-то вроде:

import calendar

months = [m.lower() for m in list(calendar.month_abbr)[1:]]

class SalesFilter(str, enum.Enum):
    this_month = 'this_month'
    last_month = 'last_month'

    this_year = 'this_year'
    last_year = 'last_year'

    for m in months:
        setattr(SalesFilter, f'{m}', m)

Есть ли способ сделать это? Может быть, с метаклассами, но я не уверен, с чего начать.

1 Ответ

1 голос
/ 10 апреля 2020

Наиболее Pythoni c способ использует Функциональный API .

import calendar
from enum import Enum

# Any iterator of (name, value) pairs. Dictionary is one possible example.
months = {}

for m in list(calendar.month_abbr)[1:]:
    months[m.lower()] = m.lower()

members = {
    'this_month': 'this_month',
    'last_month': 'last_month',
}

# Enum Members, maps Names and Values.
members.update(months)


# The Logic for mix-in.
class SalesLogic:

    def __init__(self, month):  # Several values per member are possible.
        self.month = month


# Functional API, joins Logic with Members.
SalesFilter = Enum(
    value='SalesFilter',
    names=members,
    module='your_module',
    qualname='your_module.SalesFilter',
    type=SalesLogic)


# Tests.
print(type(SalesFilter), type(SalesFilter.apr), SalesFilter.apr.name, SalesFilter.apr.value)
# <class 'enum.EnumMeta'> <enum 'SalesFilter'> apr apr

x = SalesFilter.jan  # Test suggested in comments.
if x == SalesFilter.jan and x.value == SalesFilter.jan.value and x.month == 'jan' and x.name == 'jan':
    print('True')  # The 4 tests are True.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...