Pythonのenum型(列挙型)
先日Ubuntu12.04にPython3.4をインストールしたわけだけど、そのPython3.4にはいくつか便利な機能が追加されている。それはリリースノートを読んで欲しいところだが、その中でも異色になるのがenumの導入になる。
PHPやRuby、Perl等のLLに標準でenumが導入されたのは初めてではないだろうか。Pythonにも以前からenumを実現するモジュールが作成されていたし、RubyやPerlにも同等のモジュールがある。だがこれがデフォルトに追加されるのは珍しい。
そして何よりも珍しいのは、C言語等でenumを利用している方は「enum型」として馴染みはあるかと思うが、PythonではEnumはクラスになる。
ということでそのenumについてどう気持ちがいいかまとめようとしたが、C言語など久しく書いていない上にまともに書いていないため気持ちよさがあまりわからない。ということで使い方をまとめておく。気持ちよさがわかるサンプルコードを募集中です。
パーフェクトPython (PERFECT SERIES 5)
- 作者: Pythonサポーターズ,露木誠,ルイス・イアン,石本敦夫,小田切篤,保坂翔馬,大谷弘喜
- 出版社/メーカー: 技術評論社
- 発売日: 2013/03/05
- メディア: 大型本
- 購入: 1人 クリック: 65回
- この商品を含むブログ (30件) を見る
まず、Enumは先に書いたように型ではなくクラスとして実装されている。Pythonに型を増やしても仕方がないというのがもちろんその理由かと思う。本当の理由はノートを読めば書いてあるかと思う。
最もシンプルな参考コードは以下になる。
import enum
class Cardsuit( enum.Enum):
SPADE = 1
CLUB = 2
HEART = 3
DIAMOND = 4
これはEnumクラスを継承してそのクラス内に列挙する方法だが、このシンプルな内容であれば関数型APIが用意されており以下のように書くことも出来る。
Cardsuit = enum.Enum( "Cardsuit", "SPADE CLUB HEART DIAMOND")
第一引数はEnumの名前になり、第二引数はメンバの名前を羅列した文字列になる。文字列はホワイトスペースで区切るかシーケンスにするということ。
Cardsuit = enum.Enum( "Cardsuit", "SPADE, CLUB, HEART, DIAMOND")
このようなカンマで区切っても問題ない。カンマ区切りのほうが実用的かと思う。
それぞれにはクラス継承のサンプルのように、1から4の整数が割り振られる。0オリジンではなく1オリジンになることに注意。
0オリジンやバラバラの数値を割り当てることももちろん出来る。
class Cardsuit( enum.Enum):
JORKER = 0
SPADE = 2
CLUB = 4
HEART = 6
DIAMOND = 8
一つのメンバに複数の値を設定することは出来ないが、複数のメンバに同じ値を設定することは出来る。
class Cardsuit( enum.Enum):
SPADE = 1
SPADE = 0
CLUB = 2
HEART = 3
DIAMOND = 4
これは出来ない。
class Cardsuit( enum.Enum):
JORKER = 0
SPADE = 1
SPADES = 1
CLUB = 2
CLUBS = 2
HEART = 3
HEARTS = 3
DIAMOND = 4
DIAMONDS = 4
これは出来る。
注意としては、同じ値の2つ目以降のメンバは一つ目のメンバのエイリアスになるということ。
len( Cardsuit)
[ suit for suit in Cardsuit]
としても重複する値のメンバは表示されない。重複する値のメンバも処理する必要がある場合は以下のように呼び出す。
len( Cardsuit.__members__)
[ suit for suit in Cardsuit.__members__]
もし重複した値を許容したくない場合にはユニークな値をチェックできる。
@enum.unique
class Cardsuit( enum.Enum):
JORKER = 0
SPADE = 1
SPADES = 1
CLUB = 2
HEART = 3
DIAMOND = 4
これはエラーとなる。
そして、一番上に書いた関数型APIでも自動的に値が割り振られるだけではなく自分で値の設定を行える。
Cardsuit = enum.Enum( "Cardsuit", [( "SPADE", 0), ( "CLUB", 1), ( "HEART", 2)])
Cardsuit = enum.Enum( "Cardsuit", { "SPADE": 0, "CLUB": 1, "HEART": 2})
このようにタプルを使った方法やディクショナリを使った方法がある。
そして最後に、もちろんenumなので継承したクラスの作成を行うことは出来ない。
class Base( enum.Enum):
SPADE = 1
CLUB = 2class Alt( Base):
HEART = 3
DIAMOND = 4
これはエラーになる。
いやぁ、これはいいものだ。
公式マニュアルでenumの説明に気合が入っていて面白い。最近は新機能の追加は少ないからマニュアルが充実してるのかな。
- 作者: Mark Lutz,夏目大
- 出版社/メーカー: オライリージャパン
- 発売日: 2009/02/26
- メディア: 大型本
- 購入: 12人 クリック: 423回
- この商品を含むブログ (133件) を見る
パーフェクトPython (PERFECT SERIES 5)
- 作者: Pythonサポーターズ,露木誠,ルイス・イアン,石本敦夫,小田切篤,保坂翔馬,大谷弘喜
- 出版社/メーカー: 技術評論社
- 発売日: 2013/03/05
- メディア: 大型本
- 購入: 1人 クリック: 65回
- この商品を含むブログ (30件) を見る
- 作者: ビープラウド
- 出版社/メーカー: 秀和システム
- 発売日: 2012/03/26
- メディア: 単行本
- 購入: 6人 クリック: 765回
- この商品を含むブログ (27件) を見る
- 作者: Tarek Ziade,稲田直哉,渋川よしき,清水川貴之,森本哲也
- 出版社/メーカー: KADOKAWA/アスキー・メディアワークス
- 発売日: 2010/05/28
- メディア: 大型本
- 購入: 33人 クリック: 791回
- この商品を含むブログ (90件) を見る