PEP: 354 Title: Python における列挙データのサポート (Enumerations in Python) Version: 42186 Last-Modified: 2006-1-26 Author: Ben Finney Status: Draft Type: Standards Track Content-Type: text/x-rst Created: 20-Dec-2005 Python-Version: 2.6 Post-History: 20-Dec-2005 .. _Abstract: 概要 ==== この PEP では Python の列挙型の仕様を定義します. 列挙 (enumeration) とは,一連のシンボル名を使って,任意の一意な値を束縛する ことです.一つの列挙データ中の値は,イテレーションに使ったり比較したりでき ますが,列挙型以外の値との間に本来の演算関係を持ちません. 動機 ==== 列挙型の性質は,何らかの関係にある変更不能な定数の集合を定義し,それらの定 数の本質的な意味づけに関係なく一定の順位を割り当てたい場合に役立ちます. 列挙型の古典的な例は曜日 (Sunday から Saturday) や,学校の成績等級 ('A' か ら 'D', 'F' など) です.その他にも,エラー状態値や,何らかのプロセスにおけ る状態変数などがあります. 離散的な任意の値の列を表現したければ, ``int`` や ``str`` のように,単に基 本型の値からなる集合を定義するだけでかまいません.しかし,列挙では,集合中 の値はいずれも他の値と同じにはならず,かつ (「Wednesday を 2 倍」のような) 無意味な計算を持たせないようにする必要がありますます. 仕様 ==== 列挙型は,一連の値の列を引数として型コンストラクタに渡して生成します:: >>> Weekdays = enum('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat') >>> Grades = enum('A', 'B', 'C', 'D', 'F') 値を一つも指定しない列挙型は無意味なので,引数を渡さずにコンストラクタを呼 び出すと ``EnumEmptyError`` を送出します. コンストラクタに渡した値は,生成された列挙オブジェクト (enumeration object) の属性として束縛 (bind) されます:: >>> today = Weekdays.mon 列挙型中の各値は比較できます:: >>> if today == Weekdays.fri: ... print "Get ready for the weekend" 列挙型中の値を同じ列挙型以外の値と比較しても意味はありません.ある列挙型の 値と,別の列挙型の値やその他の型のデータと比較演算すると, ``NotImplemented`` [#CMP-NOTIMPLEMENTED]_ を返します:: >>> gym_night = Weekdays.wed >>> gym_night.__cmp__(Weekdays.mon) 1 >>> gym_night.__cmp__(Weekdays.wed) 0 >>> gym_night.__cmp__(Weekdays.fri) -1 >>> gym_night.__cmp__(23) NotImplemented >>> gym_night.__cmp__("wed") NotImplemented >>> gym_night.__cmp__(Grades.B) NotImplemented このようにしておくと,ブール値を返すような比較演算を実現できます:: >>> gym_night = Weekdays.wed >>> gym_night < Weekdays.mon False >>> gym_night < Weekdays.wed False >>> gym_night < Weekdays.fri True >>> gym_night < 23 False >>> gym_night > 23 True >>> gym_night > "wed" True >>> gym_night > Grades.B True 列挙型のある値を ``str`` に型強制すると,列挙型を生成するときに指定した値を 文字列で返します:: >>> gym_night = Weekdays.wed >>> str(gym_night) 'wed' 列挙型の各値が列挙型中の何番目の値かは,属性値 ``index`` を介して整数でアク セスできます:: >>> gym_night = Weekdays.wed >>> gym_night.index 3 列挙型はイテレーション操作に使えます.イテレーションに列挙型を使うと, 列挙型データを生成するときに指定した配列を返します:: >>> print [str(day) for day in Weekdays] ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'] 列挙型の各値はハッシュ可能で,辞書のキーに使えます:: >>> plans = {} >>> plans[Weekdays.sat] = "Feed the horse" 列挙型は通常,あるデータ型で利用可能なデータの集合を指定しておき,各値に何 らかの情報を対応づけられるようにする場合に使います:: >>> for report_grade in Grades: ... report_students[report_grade] = \ ... [s for s in students if students.grade == report_grade] .. _Rationale -- Other designs considered: 問題点 -- 他の設計の検討 ======================== .. _All in one class: クラスに全てを組み込む方法 -------------------------- 列挙型の実装例の中には,列挙型とその値を単一のオブジェクトやクラスとして実 装しているものがあります. この PEP における列挙型の設計ではコンテナ型を使っており,列挙型中の各値には 単純な比較を適用できます.しかしながら,一つのクラスの中に列挙型の全ての性 質を組み込もうとするのは,実りのないわりに設計を複雑にするだけに思われます. .. _Metaclass for creating enumeration classes: メタクラスで列挙型の生成する方法 -------------------------------- この PEP で定義されている列挙型は, ``enum`` 型のインスタンスです. 他の実装の中には,各列挙型を個別のクラスとして実装したり,列挙型に共通なプ ロパティ全てを定義したメタクラスとして実装したものがあります. 各列挙型に対して (インスタンスではなく) 個別のクラスを持たせる理由の一つは, 列挙型のサブクラス化や,既存の列挙型の拡張や置き換えを可能にすることにあり ます.しかしながら,クラスを定義するということは,そのクラスのインスタンス が生成されうるということです.「全曜日の列挙」クラスがあって,各々のインス タンスに全ての曜日が入っているとすると,それに何の意味があるのか想像しがた いでしょう.こういう状況になると,大抵次は各クラスをシングルトンパターンに するという方向になり,より複雑な設計になってしまいます. 一方,この PEP で定義している列挙型は,拡張や変更のことを考えていません.も ちろん,必要なら,既存の列挙型データから新たな列挙型データを作ったり, ``enum`` 型をサブクラス化したりはできます. .. _Values related to other types: 他の型との関係演算 ------------------ 他の列挙型実装の中には,特定の整数や文字列のような列挙型以外の値と,列挙型 の各値との間に強力な関係演算の機能をうたったものもあります.しかしながら, このような機能は,列挙型の値を列挙型としての意味のないコンテキストで使うこ とになり,列挙型の設計に不要な複雑さを持ち込んでしまいます. この PEP で定義している列挙型は,列挙型を生成するときに使った値を公開してお り,他の値と等値比較できます.ただし,列挙型の外の値でできた配列との比較は 実装していません. .. _Hiding attributes of enumerated values: 列挙値の属性を隠蔽する ---------------------- 従来の設計では,列挙値の実装は可能な限り隠蔽されていて,文字列キーと配列の インデクスしか公開していませんでした. この PEP の列挙型では,列挙値がどの列挙型か,また,ある値の列挙値の文字列キー が何であるかをプログラムから判別できると便利だという点に配慮しています.こ れらの情報は,列挙値から属性値としてアクセスできます. .. _Implementation: 実装 ==== この列挙型の設計の一部は Python Cookbook のレシピ [#ENUM-RECIPE]_ に基づいています. PyPI のパッケージ ``enum`` [#ENUM-PACKAGE]_ では,この PEP で解説したデータ 型のPython 実装を提供しています. .. _References and Footnotes: 参考文献および脚注 ======================== .. [#CMP-NOTIMPLEMENTED] 比較操作が ``NotImplemented`` を戻すと, Python インタプリタは代替の比 較やその他のフォールバックを試みます. .. [#ENUM-RECIPE] Zoran Isailovski による Python Cookbook レシピ 413486, 「Python におけるファーストクラス Enum 型の実現 ("First Class Enums in Python") です. .. [#ENUM-PACKAGE] Python パッケージインデクスに登録されている ``enum`` パッケージ. .. _Copyright: 著作権表記 ========== このドキュメントはパブリックドメインのものです. .. Local Variables: mode: indented-text indent-tabs-mode: nil sentence-end-double-space: t fill-column: 70 End: