LoginSignup
5
4

More than 5 years have passed since last update.

Python3.6のEnumに自動で値を付けるautoを試す

Posted at

CやVBAのEnum

CやVBAのEnumでは、各メンバの値は指定してもしなくてもよく、指定しない場合は一つ前のメンバの数値+1になります。先頭のメンバは値を指定しないと0になります。

個人的には、VBAでCSVなどの入力ファイルを扱うときに、ファイルのフィールドを識別するためにEnum型が便利なのでよく使っていたりします。例えば次のような感じです。

Public Enum FieldID

     OrderNo = 1
     CustomerNo
     PurchaseDate
     ProductID = 10
     Price
     Units
     Amount

End Enum

この例のように、要素の数が少ない場合はありがたみが分からないかもしれませんが、数十列もあるファイルのフィールドを定義してる場合、列の追加や削除があってもすべてのメンバに番号の振りなおす必要がないので便利です。

Python3.6ではEnum型に自動で値をつける機能が追加されたので、同じようにできるのか試してみました。

PythonのEnum

Pythonには、バージョン3.4でEnumクラスが標準ライブラリに追加されました。PythonのEnumについては、こちらの記事でよくまとめられてます。

Enumライブラリのドキュメントにあるように、Python3.6ではEnumに自動的に値を付けるための、=auto()という表現が追加されました。(実際にはautoはクラスで、そのコンストラクタを呼んでいます。)

先程のVBAのコードと同じことを試してみました。

from enum import IntEnum, auto

class Field(IntEnum):

   OrderNo = 1
   CustomerNo = auto()
   PurchaseDate = auto()
   ProductID = 10
   Price = auto()
   Units = auto()
   Amount = auto()

for elm in Field:
   print(elm, int(elm))

実行結果は、

Field.OrderNo 1
Field.CustomerNo 2
Field.PurchaseDate 3
Field.ProductID 10
Field.Price 11
Field.Units 12
Field.Amount 13

となり、auto()と記述する必要はありますが、CやVBAのように自動でインクリメントするようです。ただ、最初のメンバを=auto()とすると、0ではなく1になります。

ただし、ライブラリのドキュメントに注意書きがあり、このインクリメントは実装依存とのことです。この振る舞いを恒久的にするには、自分でauto()の挙動を定義する必要があります。

auto()の返す値は、_generate_next_value_メソッドでカスタマイズ可能なので、IntEnumを継承したクラスAutoIntoEnumを作成して、_generate_next_value_を自分で定義しておきます。

from enum import IntEnum, auto

class AutoIntEnum(IntEnum):

    def _generate_next_value_(name, start, count, last_values):
        for last_value in reversed(last_values):
            try:
                return last_value + 1
            except TypeError:
                pass
        else:
            return start

class Field(AutoIntEnum):

    OrderNo = auto()
    CustomerNo = auto()
    PurchaseDate = auto()
    ProductID = 10
    Price = auto()
    Units = auto()
    Amount = auto()

for elm in Field:
    print(elm, int(elm))

これで_generate_next_value_の実装が変わってもOKです。
_generate_next_value_の中身は、Enumクラスのコードからそのままコピペしました。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4