Python Enum,何时何地使用?
Python 3.4.0 引入了 enum
这个功能。我看过了 文档,但还是不太明白它的用法。从我的角度来看,enum.Enum
就像是一个扩展版的 namedtuple
,不过这可能并不准确。所以我想了解关于 Enum
的以下几点:
- 什么时候以及在哪里使用
Enum
? - 我们为什么需要
Enum
?它有什么好处? - 到底什么是
Enum
?
1 个回答
1. 什么时候以及在哪里使用枚举(enum)?
- 当你有一个变量,它的值只能是有限的几种可能性时。
比如说,一周的天数:
class Weekday(Enum):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
SUNDAY = 7
2. 为什么我们需要枚举?它有什么好处?
枚举的好处在于它给常量起了个名字,这样代码更容易读懂;而且枚举中的每个成员不能被重新赋值,这让 Python 的枚举变得半常量(因为枚举本身还是可以被重新赋值的)。
除了让代码更易读,调试的时候也更简单,因为你可以看到名字和对应的值,而不仅仅是值。
你还可以给枚举添加想要的行为。
例如,任何使用过 datetime 模块的人都知道,datetime
和 date
对一周的天数有两种不同的表示方式:0-6 或 1-7。与其自己去记,不如给 Weekday
枚举添加一个方法,从 datetime
或 date
实例中提取出天数,并返回对应的枚举成员:
@classmethod
def from_date(cls, date):
return cls(date.isoweekday())
3. 枚举到底是什么?
枚举是一种 类型,它的成员是命名常量,所有成员都属于(或应该属于)一个逻辑上的值的组。到目前为止,我已经为以下内容创建了
Enum
:- the days of the week - the months of the year - US Federal Holidays in a year
FederalHoliday
是我最复杂的一个;它使用了 这个方法,并且有方法可以返回给定年份假期的实际日期,如果查询的日期是个假期(或者跳过的日期范围包括假期或周末),还可以返回下一个工作日,以及一整年的假期日期集合。这里是它的代码:
class FederalHoliday(AutoEnum):
NewYear = "First day of the year.", 'absolute', Month.JANUARY, 1
MartinLutherKingJr = "Birth of Civil Rights leader.", 'relative', Month.JANUARY, Weekday.MONDAY, 3
President = "Birth of George Washington", 'relative', Month.FEBRUARY, Weekday.MONDAY, 3
Memorial = "Memory of fallen soldiers", 'relative', Month.MAY, Weekday.MONDAY, 5
Independence = "Declaration of Independence", 'absolute', Month.JULY, 4
Labor = "American Labor Movement", 'relative', Month.SEPTEMBER, Weekday.MONDAY, 1
Columbus = "Americas discovered", 'relative', Month.OCTOBER, Weekday.MONDAY, 2
Veterans = "Recognition of Armed Forces service", 'relative', Month.NOVEMBER, 11, 1
Thanksgiving = "Day of Thanks", 'relative', Month.NOVEMBER, Weekday.THURSDAY, 4
Christmas = "Birth of Jesus Christ", 'absolute', Month.DECEMBER, 25
def __init__(self, doc, type, month, day, occurrence=None):
self.__doc__ = doc
self.type = type
self.month = month
self.day = day
self.occurrence = occurrence
def date(self, year):
"returns the observed date of the holiday for `year`"
if self.type == 'absolute' or isinstance(self.day, int):
holiday = Date(year, self.month, self.day)
if Weekday(holiday.isoweekday()) is Weekday.SUNDAY:
holiday = holiday.replace(delta_day=1)
return holiday
days_in_month = days_per_month(year)
target_end = self.occurrence * 7 + 1
if target_end > days_in_month[self.month]:
target_end = days_in_month[self.month]
target_start = target_end - 7
target_week = list(xrange(start=Date(year, self.month, target_start), step=one_day, count=7))
for holiday in target_week:
if Weekday(holiday.isoweekday()) is self.day:
return holiday
@classmethod
def next_business_day(cls, date, days=1):
"""
Return the next `days` business day from date.
"""
holidays = cls.year(date.year)
years = set([date.year])
while days > 0:
date = date.replace(delta_day=1)
if date.year not in years:
holidays.extend(cls.year(date.year))
years.add(date.year)
if Weekday(date.isoweekday()) in (Weekday.SATURDAY, Weekday.SUNDAY) or date in holidays:
continue
days -= 1
return date
@classmethod
def year(cls, year):
"""
Return a list of the actual FederalHoliday dates for `year`.
"""
holidays = []
for fh in cls:
holidays.append(fh.date(year))
return holidays
备注:
Date
来自 我的 dbf 包增强版的
xrange
(支持日期范围)也是自定义的,但我想我没有在任何地方包含它;下次我弄这个的时候会把它放进我的dbf
包里。声明:我是 Python 标准库
Enum
的作者,enum34
的回溯版本,以及 高级枚举(aenum
) 库的作者。