Ответ 1
1. Когда и где использовать перечисления?
- Когда у вас есть переменная, которая принимает один из ограниченного набора возможных значений.
Например, дни недели:
class Weekday(Enum):
MONDAY = 1
TUESDAY = 2
WEDNESDAY = 3
THURSDAY = 4
FRIDAY = 5
SATURDAY = 6
SUNDAY = 7
2. Зачем нам перечислить? Каковы преимущества?
-
Перечисления выгодны, потому что они дают имя константе, что делает код более удобочитаемым; и потому что отдельные члены не могут отскочить, делая Python Enums полупостоянными (потому что сам
Enum
все еще может восстанавливаться). -
Помимо более читаемого кода, отладка также проще, так как вы видите имя вместе со значением, а не только значение
-
Желаемое поведение может быть добавлено в Enums
Например, как любой, кто работал с DateTime модуль знает, datetime
и date
datetime
и date
имеют два различных represntations для дней недели: 0-6 или 1-7. Вместо того, чтобы следить за этим, мы можем добавить метод к перечислению Weekday
чтобы извлечь день из экземпляра datetime
или date
и вернуть соответствующий член перечисления:
@classmethod
def from_date(cls, date):
return cls(date.isoweekday())
3. Что такое Enum?
-
Enum - это тип, члены которого называются константами, все они принадлежат (или должны) логической группе значений. Пока я создал
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, occurance=None):
self.__doc__ = doc
self.type = type
self.month = month
self.day = day
self.occurance = occurance
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.occurance * 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 stdlib
Enum
,enum34
backport и библиотеки Advanced Enumeration (aenum
).