いっこ前のでメタクラスでシングルトンとかやりましたが、なんとなく必要になったEnum型の実装もメタクラスでやってみた。
いや先人の知恵でEnum型は実装済みだったんですが、Enumっぽいクラスのサブクラスにするのがなんとなくやだったので(;´∀`)
つまりはメタクラスで完結できないかってことでした
で結果。メタクラスで完結できます。
要はEnumの値となる名前のクラスを定義して、それのインスタンスで元クラスのフィールドを置き換えてやればいい。*1
class EnumType(type): def __init__(cls, name, bases, dic): super(EnumType, cls).__init__(name, bases, dic) reprFunc = lambda self: "<class %s, value=%s>" % (self.__class__.__name__, self.value) strFunc = lambda self: "%d" % self.value def newFunc(cls, *args, **kwargs): """新規インスタンス生成を阻止します""" raise RuntimeError("Create another instance of EnumType is not allowed") for key, value in dic.items(): if not key.startswith('_'): clsType = type("%s.%s" % (cls.__name__, key), (cls,), {}) item = clsType() setattr(cls, key, item) setattr(item, 'value', value) setattr(item, 'name', key) setattr(clsType, '__repr__', reprFunc) setattr(clsType, '__str__', strFunc) setattr(clsType, '__new__', newFunc)
使い方:
class Key(metaclass=EnumType): A = 0 B = 1 C = 2 print(Key.A) print(Key.B) print(Key.C) print(repr(Key.A)) print(repr(Key.B)) print(repr(Key.C))
作ったはいいが役に立つのかコレ
*1:コンストラクタが連続起動している気がしますが無視します