『Effective Python』の続き。水際で防げ。 www.effectivepython.com
『Effective Python』のChapter 4冒頭に筆者は次のように述べている。
Metaclass are often mentioned in lists of Python's features, but few understand what they accomplish in practice.
『Effective Python』 Chapter 4
「Pythonの特徴の1つによくメタクラスが挙げられますが、実際にどう使うのかを理解している人は少ないです。」と訳せるだろうか。*1 そこで筆者はメタクラスの応用例としてサブクラスの検査、登録、注釈を挙げている。 今回のItem 33はサブクラスの検査を取り上げている。
下記の例は、多角形をPythonのクラスで構成する例である。 多角形の厳密な定義は真面目な幾何学の本に任せるとして、頂点が3つ以上であることを検査する機能をメタクラスに織り込んでいる。
class ValidatePolygon(type): def __new__(meta, name, bases, class_dict): # Don't validate the abstract Polygon class if bases != (object,): if class_dict['sides'] < 3: raise ValueError('Polygons need 3+ sides') return type.__new__(meta, name, bases, class_dict) class Polygon(object, metaclass=ValidatePolygon): sides = None # Specified by subclasses @classmethod def interior_angles(cls): return (cls.sides - 2) * 180 class Triangle(Polygon): sides = 3
ここで、多角形だといっているのに直線を定義しようとして、
class Line(Polygon): print('Before sides') sides = 1 print('After sides')
とするときちんとValueError
が送出される。
*1:accomplishは達成とかそういう意味であるが…