[解決済み] Python、Enum型は何のためにあるのか?重複
質問
Python 3.4では、標準ライブラリにEnumライブラリが追加されました。
enum
. をバックポートすることができます。
enum
は Python 2.4 から 2.7 (そして 3.1 から 3.3 でも) で動作するバックポートが得られます。
enum34
をpypiに追加しました。
しかし、私たちはこの新しいモジュールなしでかなりの期間うまくやってこれました - ではなぜ今、私たちはこのモジュールを手に入れたのでしょうか?
私は他の言語からenumの目的について一般的な考えを持っています。Pythonでは、以下のように素のクラスを使って、これをenumと呼ぶのが一般的でした。
class Colors:
blue = 1
green = 2
red = 3
これは、APIで値の正規表現を作成する場合などに使用することができます。
function_of_color(Colors.green)
これに批判があるとすれば、ミュータブルであること、(簡単に)反復処理できないこと、そして、整数のセマンティクスをどうやって知るのか、ということです。
2
?
それならnamedtupleのようなものを使えばいいと思うのですが、これは不変なのでしょうか?
>>> Colors = namedtuple('Colors', 'blue green red')
>>> colors = Colors('blue', 'green', 'red')
>>> colors
Colors(blue='blue', green='green', red='red')
>>> list(colors)
['blue', 'green', 'red']
>>> len(colors)
3
>>> colors.blue
'blue'
>>> colors.index(colors.blue)
0
namedtupleの作成は少し冗長なので(それぞれの名前を2回書かなければならない)、ややエレガントではありません。色の "number" を取得するのも、少し優雅ではありません。
colors
と2回書かなければならない)。値のチェックは文字列で行う必要があり、少し効率が悪くなる。
というわけで、列挙に戻ります。
列挙型は何のためにあるのでしょうか?言語にとってどんな価値があるのでしょうか?いつ使って、いつ避けるべきなのか?
どのように解決するのですか?
<ブロッククオート列挙型は何のためにあるのですか?列挙型は言語にとってどのような価値を生むのでしょうか?いつ使って、いつ避けるべきなのか?
Enum型がPythonに導入されたのは PEP 435 . 与えられた理由は
列挙型のプロパティは、不変で関連性のある定数値のセットを定義するのに便利で、意味的な意味を持つことも持たないこともあります。
この目的のために数値や文字列を使用する場合、次のように特徴付けることができます。 "マジックナンバー"。 または "魔法の文字列" と呼ばれます。数字はほとんど意味を持ちませんし、文字列は簡単に混同されます (大文字小文字、スペル、スネークケースかキャメルケースか)。
曜日と学校の成績は、この種の値のコレクションの例です。
の例です。 docs :
from enum import Enum
class Color(Enum):
red = 1
green = 2
blue = 3
素のクラスと同様に、これはnamedtupleの例よりもずっと読みやすくエレガントで、また不変であり、以下で見るようにさらなる利点があります。
厳密には支配的です。enum メンバの型は enum
>>> type(Color.red)
<enum 'Color'>
>>> isinstance(Color.green, Color)
True
これにより、Enumの定義にあるメンバーに対して機能を定義することができます。値に対する機能を定義することは、他の先行するメソッドで達成することができますが、それは非常にエレガントではないでしょう。
改善されました。文字列の強制
文字列表現は人間が読みやすく、reprはより多くの情報を持っています。
>>> print(Color.red)
Color.red
>>> print(repr(Color.red))
<Color.red: 1>
これはマジックナンバーよりも改善されており、namedtupleからの文字列よりも優れている可能性さえありますね。
イテレーション(パリティ)。
enumも反復処理をサポートしています(namedtupleのような、素のクラスはそうでもないような)。
>>> for color in Color:
print(color)
Color.red
Color.green
Color.blue
は
__members__
属性は、列挙型の名前とそれぞれの列挙型オブジェクトの順序付きマッピングです(namedtuple の
_asdict()
関数に似ています)。
>>> Color.__members__
mappingproxy(OrderedDict([('red', <Color.red: 1>), ('green', <Color.green: 2>),
('blue', <Color.blue: 3>)]))
pickleで対応(パリティ)
enumのシリアライズとデシリアライズができます(心配している人がいたら念のため)。
>>> import pickle
>>> color.red is pickle.loads(pickle.dumps(color.red))
True
改善されました。エイリアス
これは素のクラスにはない良い機能で、エイリアスがあることを伝えるのは難しいでしょう。
namedtuple
.
class Color(Enum):
red = 1
green = 2
blue = 3
really_blue = 3
エイリアスは正規名の後に来ますが、どちらも同じものです。
>>> Color.blue is Color.really_blue
True
値の衝突を避けるためにエイリアスを禁止する必要がある場合には
enum.unique
デコレータを使います(厳密には支配的な機能です)。
厳密に支配的な機能: 比較は
is
この列挙型のテストは
is
で、これはプロセス中の単一のオブジェクトの同一性を高速にチェックするものです。
>>> Color.red is Color.red
True
>>> Color.red is Color.blue
False
>>> Color.red is not Color.blue
True
等号のテストは同様に機能しますが、同一性のテストは
is
を使った同一性のテストは最適です。
他のPythonクラスとは異なるセマンティクス
Enumクラスは通常のPythonの型とは異なるセマンティクスを持っています。Enumの値はEnumのインスタンスであり、それらの値のメモリ上のシングルトンである - それらをインスタンス化するための他の目的はありません。
>>> Color.red is Color(1)
これは重要なことで、もしかしたらデメリットかもしれませんが、この次元で比較することは、リンゴとオレンジを比較することです。
順序付きであることを前提としない列挙型
Enum クラスはメンバーがどのような順序で作成されるかを知っていますが、列挙型は順序を仮定していません。これは、列挙される可能性のある多くのものが自然な順序を持たないため、順序が恣意的になってしまうという特徴です。
しかし、列挙に順序を与えることはできます(次のセクションを参照してください)。
サブクラス化
メンバーが宣言されているEnumをサブクラス化することはできませんが はできます。 のOrderedEnumレシピを参照してください)。 ドキュメント ).
これは機能です - メンバーを持つEnumをサブクラス化することはほとんど意味がありませんが、再び、比較はリンゴとオレンジです。
いつ
enum.Enum
?
これは Python の新しい標準的な列挙です。Collaboratorはあなたの列挙がこれらの列挙のように動作することを期待します。
コード内の列挙データの正規のソースがあり、任意のデータではなく、正規の名前を使用するように明示的に指定したい場合はどこでも使用します。
例えば、あなたのコードで、ユーザーにそれが
"Green"
,
"green"
2、または
"Greene"
が、しかし
Color.green
- はenum.Enumオブジェクトを使用します。これは明示的かつ具体的です。
にはたくさんの例とレシピがあります。 ドキュメント .
どのような場合に避けるべきですか?
自分で転がしたり、魔法の数字や文字列を推測させるのはやめましょう。避けるべきではありません。受け入れるのです。
しかし、歴史的な理由で enum のメンバが整数であることが要求される場合、そのような場合は
IntEnum
があります。これは同じ振る舞いをしますが、組み込みの
int
をサブクラス化する前に
Enum
. から
IntEnum
のヘルプを参照してください。
class IntEnum(builtins.int, Enum)
のインスタンスとしてテストされることがわかります。
int
.
関連
-
[解決済み] for'ループでインデックスにアクセスする?
-
[解決済み] Pythonで現在時刻を取得する方法
-
[解決済み] オブジェクトの種類を決定しますか?
-
[解決済み] Pythonのswitch文の代用品?
-
[解決済み] C#の[Flags]Enum属性の意味とは?
-
[解決済み] Pythonで型をチェックする標準的な方法は何ですか?
-
[解決済み] Pythonで'Enum'を表現するにはどうしたらいいですか?
-
[解決済み] Javaでenumを繰り返し処理するためのforループ
-
[解決済み] DataFrameに日付間の日数カラムを追加する pandas
-
[解決済み] PythonでintをEnumに変換する方法は?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] 「is" 演算子が整数に対して予期せぬ振る舞いをする。
-
[解決済み] PythonでファイルのMD5チェックサムを計算するには?重複
-
[解決済み] Django のテストデータベースをメモリ上だけで動作させるには?
-
[解決済み] 小数点以下1桁を取得する[重複]。
-
[解決済み] Python Logging でログメッセージが2回表示される件
-
[解決済み] PyQtアプリケーションのスレッド化。QtスレッドとPythonスレッドのどちらを使うか?
-
[解決済み] Pythonで、ウェブサイトが404か200かを確認するためにurllibをどのように使用しますか?
-
[解決済み] djangoのQueryDictをPythonのDictに変更するには?
-
[解決済み] データクラスとtyping.NamedTupleの主な使用例
-
[解決済み] Pythonでリストが空かどうかをチェックする方法は?重複