Sunday, August 30, 2009

Metaclass in Python

Here is a way to do this and subclass it.

class CustomMetaclass(type):
    def __init__(cls, name, bases, dct):
    print "Creating class %s using CustomMetaclass" % name
    super(CustomMetaclass, cls).__init__(name, bases, dct)


class BaseClass(object):
    __metaclass__ = CustomMetaclass

class Subclass1(BaseClass):
    pass

And now, an example that actually means something, this will automatically make the variables in the list "attributes" set on the class, and set to None.
def init_attributes(name, bases, dict):
    if 'attributes' in dict:
        for attr in dict['attributes']:
            dict[attr] = None
    return type(name, bases, dict)


class Initialised(object):
    __metaclass__ = init_attributes
    attributes = ['foo', 'bar', 'baz']


print 'foo =>', Initialised.foo
# output=>
foo => None


Here is an even more concrete example, showing how you can subclass 'type' to make a metaclass that performs an action when the class is created. This is quite tricky:

class MetaSingleton(type):
    instance = None
    def __call__(cls, *args, **kw):
        if cls.instance is None:
            cls.instance = super(MetaSingleton, cls).__call__(*args, **kw)
        return cls.instance

class Foo(object):
    __metaclass__ == MetaSingleton

a = Foo()
b = Foo()
assert a is b

No comments: