动态添加枚举属性



首先,我知道Python中的Enum是不可变的。

我正在尝试获得一个枚举,它将每个月作为一个属性,还包含其他枚举值,例如:

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)

有办法做到这一点吗?也许是元类,但我不确定从哪里开始。

最Python的方法是使用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.

最新更新