見出し画像

[Python] Enumクラスを拡張して使用する


はじめに

以前、Pythonで列挙型を使う場合について、下記の記事でまとめました。

今回は、Pythonで作成したEnumクラスに対して要素を追加したEnumクラスを拡張して作成するために、調べたことと、対応方法について、まとめていきます。

動作環境

  • windows11

  • Jupyter Notebook 6.5.2(Python 3.10.9)

やりたいこと

VegetablesというEnumクラスを定義しました。

from enum import Enum

class Vegetables(Enum):
    Potato = 0
    Onion = 1
    Carrot = 2

このVegetablesクラスに対して、要素を追加したSummerVegetablesというクラスを作成したいと思います。

作成したEnumクラスを継承

作成したVegetablesクラスの継承して、下記のように実装しました。

class SummerVegetables(Vegetables):
    corn = 4
    Zucchini = 5

実行結果は、エラーです。

Enum型を継承した際の実行画面

エラーの内容は、TypeError: SummerVegetables: cannot extend enumeration 'Vegetables'。Vegetablesを拡張できません…とのこと。

公式ドキュメントで、Enum型の記載内容を確認してみます。
Enumは、class文を使って定義を行うことができるが、は通常のクラスではないとの記載があります。

注釈
Enum の作成にclass 文を使用するものの、Enum は通常の Python クラスではありません。詳細は Enum はどう違うのか? を参照してください。

Python標準ライブラリ enum列挙型のサポート Enum の作成

また、サブクラス化の制限として、スーパークラス側(今回だと、Vegetablesクラス)に要素が無い場合は、継承することができるようです。

実装して動作確認してみました。

class Vegetables(Enum):
    pass

class SummerVegetables(Vegetables):
    Corn = 4
    Zucchini = 5

for kind in SummerVegetables:
    print(kind, kind.value)

実行したところ、正常終了し、動作することはできました。
しかし、今回使用したいケースは、これには当てはまりません…

スーパークラス側に要素が無い場合のEnumクラスを継承した際の実行画面

対応方法

対応方法は、下記のサイトを参考にしました。

Enum()を呼び出して、動的にEnumクラスを生成します。

Python: Enumクラスを拡張する

関数として呼び出しできるということかな?と思い、ドキュメントを確認してみました。
Enumクラスのページ内に、機能APIというセクションを発見しました。

第1引数では、列挙型の名前を指定します。
第2引数では、列挙型のメンバー、名前、値に設定するデータを渡すことができます。

  • 文字列

  • リスト

  • 名前と値をペアにしたタプル

  • 名前をキーに、値をバリューに設定した辞書

上記4つのうち、文字列、リストで渡す場合、名前を渡すこととなります。
これらの場合。値は、1から順に設定されます。

それでは、実装していきます。

summer_vegetables_value = {kind.name: kind.value for kind in Vegetables} | {'Corn': 4, 'Zucchini': 5}
SummerVegetables = Enum('SummerVegetables', summer_vegetables_value)

for kind in SummerVegetables:
    print(kind,kind.value)

実行したところ、正常に動作することが確認できました!

Enumクラスを拡張した実行結果

コードの詳細について、順番に説明していきます。

辞書型の連結

拡張するEnumクラスのSummerVegetablesに対して名前、値に設定する、辞書型のデータを作成していきます。
EnumクラスのVegetablesから、名前と値を取得して辞書型に取得して設定し、追加で、SummerVegetablesに追加する名前、値を設定しています。

summer_vegetables_value = {kind.name: kind.value for kind in Vegetables} | {'Corn': 4, 'Zucchini': 5}

Python3.9以降、|演算子を使用して、辞書を連結することができるようになりました。

Python3.9以前のバージョンでは、**をつけてアンパックして辞書を連結します。

summer_vegetables_value = {
    **{kind.name: kind.value for kind in Vegetables},
    **{'Corn': 4,'Zucchini': 5}
}

Enumの機能APIを呼び出す

Enum関数を呼び出します。
第1引数として、列挙型の名前を、第2引数には、列挙型のメンバーを、名前、値として設定する辞書型を渡しています。

SummerVegetables = Enum('SummerVegetables', summer_vegetables_value)

まとめ

今回は、Pythonで作成したEnumクラスに対して要素を追加したEnumクラスを拡張する実装についてまとめました。

参考サイト


この記事が気に入ったらサポートをしてみませんか?