Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Enum, when and where to use?

Python 3.4.0 introduced enum, I've read the doc but still don't know the usage of it. From my perspective, enum.Enum is an extended namedtuple type, which may not be true. So these are what I want to know about Enum:

  1. When and where to use Enum?
  2. Why do we need Enum? What are the advantages?
  3. What exactly is an Enum?
like image 772
laike9m Avatar asked Mar 23 '14 03:03

laike9m


People also ask

When should you use enums in Python?

Python enums are useful to represent data that represent a finite set of states such as days of the week, months of the year, etc.

When should I use enum?

You should use enum types any time you need to represent a fixed set of constants. That includes natural enum types such as the planets in our solar system and data sets where you know all possible values at compile time—for example, the choices on a menu, command line flags, and so on.

Where should enum be placed?

Put the enums in the namespace where they most logically belong. (And if it's appropriate, yes, nest them in a class.)

What is the benefit of using enums?

The benefits of using enumerations include: Reduces errors caused by transposing or mistyping numbers. Makes it easy to change values in the future. Makes code easier to read, which means it is less likely that errors will creep into it.


1 Answers

1. When and where to use enums?

  • When you have a variable that takes one of a limited set of possible values.

For example, the days of the week:

class Weekday(Enum):     MONDAY = 1     TUESDAY = 2     WEDNESDAY = 3     THURSDAY = 4     FRIDAY = 5     SATURDAY = 6     SUNDAY = 7 

2. Why do we need enum? What are the advantages?

  • Enums are advantageous because they give a name to a constant, which makes code more readable; and because the individual members cannot be rebound, making Python Enums semi-constant (because the Enum itself could still be rebound).

  • Besides more readable code, debugging is also easier as you see a name along with the value, not just the value

  • Desired behavior can be added to Enums

For example, as anyone who has worked with the datetime module knows, datetime and date have two different representations for the days of the week: 0-6 or 1-7. Rather than keep track of that ourselves we can add a method to the Weekday enum to extract the day from the datetime or date instance and return the matching enum member:

    @classmethod     def from_date(cls, date):         return cls(date.isoweekday()) 

3. What exactly is Enum?

  • Enum is a type, whose members are named constants, that all belong to (or should) a logical group of values. So far I have created Enums for:

    - the days of the week - the months of the year - US Federal Holidays in a year 

FederalHoliday is my most complex; it uses this recipe, and has methods to return the actual date the holiday takes place on for the year given, the next business day if the day in question is a holiday (or the range of days skipped includes the holiday or weekends), and the complete set of dates for a year. Here it is:

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 

Notes:

  • Date is from my dbf package

  • the enhanced xrange (supporting a range of dates) is also custom, but I don't think I have included it anywhere; I'll stuff it in my dbf package next time I tinker with it.

  • Disclosure: I am the author of the Python stdlib Enum, the enum34 backport, and the Advanced Enumeration (aenum) library.

like image 78
Ethan Furman Avatar answered Sep 25 '22 04:09

Ethan Furman