使用枚举类

当我们需要定义常量时,一个办法是用大写变量通过整数来定义,例如月份:

  1. JAN = 1
  2. FEB = 2
  3. MAR = 3
  4. ...
  5. NOV = 11
  6. DEC = 12

好处是简单,缺点是类型是int,并且仍然是变量。

更好的方法是为这样的枚举类型定义一个class类型,然后,每个常量都是class的一个唯一实例。Python提供了Enum类来实现这个功能:

  1. from enum import Enum
  2. Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

这样我们就获得了Month类型的枚举类,可以直接使用Month.Jan来引用一个常量,或者枚举它的所有成员:

  1. for name, member in Month.__members__.items():
  2. print(name, '=>', member, ',', member.value)

value属性则是自动赋给成员的int常量,默认从1开始计数。

如果需要更精确地控制枚举类型,可以从Enum派生出自定义类:

  1. from enum import Enum, unique
  2. @unique
  3. class Weekday(Enum):
  4. Sun = 0 # Sun的value被设定为0
  5. Mon = 1
  6. Tue = 2
  7. Wed = 3
  8. Thu = 4
  9. Fri = 5
  10. Sat = 6

@unique装饰器可以帮助我们检查保证没有重复值。

访问这些枚举类型可以有若干种方法:

  1. >>> day1 = Weekday.Mon
  2. >>> print(day1)
  3. Weekday.Mon
  4. >>> print(Weekday.Tue)
  5. Weekday.Tue
  6. >>> print(Weekday['Tue'])
  7. Weekday.Tue
  8. >>> print(Weekday.Tue.value)
  9. 2
  10. >>> print(day1 == Weekday.Mon)
  11. True
  12. >>> print(day1 == Weekday.Tue)
  13. False
  14. >>> print(Weekday(1))
  15. Weekday.Mon
  16. >>> print(day1 == Weekday(1))
  17. True
  18. >>> Weekday(7)
  19. Traceback (most recent call last):
  20. ...
  21. ValueError: 7 is not a valid Weekday
  22. >>> for name, member in Weekday.__members__.items():
  23. ... print(name, '=>', member)
  24. ...
  25. Sun => Weekday.Sun
  26. Mon => Weekday.Mon
  27. Tue => Weekday.Tue
  28. Wed => Weekday.Wed
  29. Thu => Weekday.Thu
  30. Fri => Weekday.Fri
  31. Sat => Weekday.Sat

可见,既可以用成员名称引用枚举常量,又可以直接根据value的值获得枚举常量。

小结

Enum可以把一组相关常量定义在一个class中,且class不可变,而且成员可以直接比较。

参考源码

use_enum.py

原文: https://wizardforcel.gitbooks.io/liaoxuefeng/content/py3/51.html