1

First of, I know Enum in Python are immutable.

I'm trying to get an enum that has each month as an attribute and also other enum values, for example:

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' 

I wonder if there's a way to generate those months dynamically, I'd like to do something like:

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) 

Is there a way to do that? Maybe with metaclasses, but I'm not sure where to start.

3
  • You can add those month attributes to the SalesFilter class after defining the basic class — i.e. after and outside the class definition. Commented Apr 9, 2020 at 21:31
  • 2
    Which of those should be enum members and which should be plain attributes? Commented Apr 9, 2020 at 22:32
  • @martineau That didn't work, cause the attributes are not Enum values so you cannot compare say: ` x = SalesFilter.jan x == SalesFilter.jan # False cause now x is a string ` Commented Apr 9, 2020 at 22:53

1 Answer 1

2

The most Pythonic way is using Functional 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( 'SalesFilter', 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. 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.