『Effective Python』の続き。末端の人間頑張れメソッドダメ、ゼッタイ。 www.effectivepython.com
メタクラスの活用第二弾として、クラスの登録を挙げている。 PythonのオブジェクトをJSON文字列へシリアライズ、JSON文字列からPythonオブジェクトへデシリアライズする機能を備えたクラスを定義する。
class BetterSerializable(object): def __init__(self, *args): self.args = args def serialize(self): return json.dumps({ 'class': self.__class__.__name__, 'args': self.args, }) def __repr__(self): return '%s(%s)' % ( self.__class__.__name__, ', '.join(str(x) for x in self.args)) registry = {} def register_class(target_class): registry[target_class.__name__] = target_class def deserialize(data): params = json.loads(data) name = params['class'] target_class = registry[name] return target_class(*params['args'])
このクラスを継承するとシリアライズ及びデシリアライズが可能となる。
class EvenBetterPoint2D(BetterSerializable): def __init__(self, x, y): super().__init__(x, y) self.x = x self.y = y register_class(EvenBetterPoint2D)
問題は、毎回毎回継承して作ったクラスをregister_class
で登録しなければならないことである。
単純に面倒である。
そこで、メタクラスを使えば解決しますよ、という話である。
class Meta(type): def __new__(meta, name, bases, class_dict): cls = type.__new__(meta, name, bases, class_dict) register_class(cls) return cls class RegisteredSerializable(BetterSerializable, metaclass=Meta): pass
こうすればRegisteredSerializable
を定義した時点で自動的にregister_class
が走って登録してくれる。
よく、何らかのトラブルの解決案でダブルチェックをするとか、よく注意するとか、「末端の人間頑張れメソッド」が採用される。 何事も自動化、とは行かないが、このようにスマートな解決策を見出したいものである。