over 3 years ago

Validate Subclasses with Metaclasses

metaclasses 最簡單的應用之一是檢查定義 class 時有沒有照規定來

下面的程式在定義 Line 會丟出 ValueError

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 Line(Polygon):
    sides = 1

相關

Python 2 和 3 在使用 metaclasses 時語法完全不一樣,six 有提供 with_metaclass 方面我們寫出相容的程式碼。

with_metaclass 程式碼有點神奇

def with_metaclass(meta, *bases):
    """Create a base class with a metaclass."""
    # This requires a bit of explanation: the basic idea is to make a dummy

    # metaclass for one level of class instantiation that replaces itself with

    # the actual metaclass.

    class metaclass(meta):

        def __new__(cls, name, this_bases, d):
            return meta(name, bases, d)
    return type.__new__(metaclass, 'temporary_class', (), {})

改寫 Polygon

class Polygon(with_metaclass(ValidatePolygon, object)):
    sides = None  # Specified by subclasses


    @classmethod
    def interior_angles(cls):
        return (cls.sides - 2) * 180
← Effective Python 心得筆記: Item 32 Effective Python 心得筆記: Item 34 →
 
comments powered by Disqus