Python3.4のEnum(列挙型)を使ってみた
先日、Python3.4が正式リリースされたので、一番気になっていた Enum(列挙型)を使ってみた。
enum — Python 3.4.0 documentation(英語)
Enumを定義
from enum import Enum class Color(Enum): red = 1 green = 2 blue = 3
このように、属性の名前(name)と値(value)を定義していく。
値(value)はintに限らず、文字列やタプルでもよい。
class Color2(Enum): red = '#ff0000' green = '#00ff00' blue = '#0000ff' class Color3(Enum): red = (255, 0, 0) green = (0, 255, 0) blue = (0, 0, 255)
もっとシンプルに書くこともできる。(namedtupleのように)
Color = Enum('Color', 'red green blue')
この場合、値(value)は前から順番に1,2,3..となる。(0からではなく1からスタート)
nameとvalueプロパティ
Enumのメンバーはnameとvalueプロパティを持つ。
>>> Color.red <Color.red: 1> >>> Color.red.name 'red' >>> Color.red.value 1
nameやvalueから、メンバーを指定することもできる。
>>> Color(2) <Color.green: 2> >>> Color['blue'] <Color.blue: 3>
メソッド
メソッドやクラスメソッドを追加できる。
class Color(Enum): red = 1 green = 2 blue = 3 # メンバーのメソッド (self=各メンバー) def to_japanese(self): return '赤緑青'[self.value - 1] # クラスメソッド @classmethod def favorite_color(cls): return cls.blue
メソッドを使ってみる。
>>> Color.red.to_japanese() '赤' >>> Color.favorite_color() <Color.blue: 3> >>> Color.favorite_color().to_japanese() '青'
イテレート
Enum型はイテレート可能。
forでループしたり、
>>> for c in Color: ... print(c) Color.red Color.green Color.blue
リストにキャストしたり。
>>> list(Color) [<Color.red: 1>, <Color.green: 2>, <Color.blue: 3>]
その他
他に気になった点。
- Enum型は、ハッシュ可能なので、辞書(dict)のキーにも使える。
- 値を整数に限定した IntEnum というのもある。(ただ、通常は Enum を使えとも書いてある。)
- 定義済みのEnumを継承して、後からメンバーを追加することはできない。
- 別の名前で同じ値にすることも可能(値の重複)。ただし、最初のメンバー以外はエイリアスという扱いになり、イテレート時にでてこない。
- __member__は、エイリアスも含めたすべてのメンバーが含まれた辞書。
何に使う?
今までに書いたコードで言えば、東西南北を、'N','E','W','S'などの文字列で定義していたのを、Enumにすることですっきりするかなと思う。あとは、曜日とか色名かな?
曜日だと、こんな感じだろうか?
from enum import Enum from datetime import date class DayOfWeek(Enum): Monday = 0 Tuesday = 1 Wednesday = 2 Thursday = 3 Friday = 4 Saturday = 5 Sunday = 6 def weekday(self): return self.value def iso_weekday(self): return self.value + 1 def to_japanese(self): return '月火水木金土日'[self.value] @property def shortname(self): return self.name[:3] @classmethod def from_date(cls, d): return cls(d.weekday()) w = DayOfWeek.from_date(date(2014, 3, 19)) print(w) # DayOfWeek.Wednesday print(w.name) # 'Wednesday' print(w.value) # 2 print(w.weekday()) # 2 print(w.iso_weekday()) # 3 print(w.to_japanese()) # '水' print(w.shortname) # 'Wed'
おー、なんか面白い。