Meta classes

Table of Contents

Overview

class Meta(type):
    def __new__(meta, name, bases, class_dict):
        print 'Meta.__new__'
        print 1, meta
        print 2, name
        print 3, bases
        print 4, class_dict
        return type.__new__(meta, name, bases, class_dict)

    def __init__(cls, name, bases, class_dict):
        print 'Meta.__init__'

    def __call__(cls, *args, **kwargs):
        print 'Meta.__call__'
        return type.__call__(cls, *args, **kwargs)


print 'Before class Foo'


class Foo(object):
    __metaclass__ = Meta

    print 'Defining class Foo (1)'

    def __new__(cls):
        print 'Foo.__new__'
        return super(Foo, cls).__new__(cls)

    print 'Defining class Foo (2)'

    def __init__(self):
        print 'Foo.__init__'

    print 'Defining class Foo (3)'

print 'After class Foo'

print '--------------------------------------------------------------------------------'

print 'Before instance foo'
foo = Foo()
print 'After instance foo'
Before class Foo
Defining class Foo (1)
Defining class Foo (2)
Defining class Foo (3)
Meta.__new__
1 <class '__main__.Meta'>
2 Foo
3 (<type 'object'>,)
4 {'__module__': '__main__', '__metaclass__': <class '__main__.Meta'>, '__new__': <function __new__ at 0x7f697432a050>, '__init__': <function __init__ at 0x7f697432a0c8>}
Meta.__init__
After class Foo
--------------------------------------------------------------------------------
Before instance foo
Meta.__call__
Foo.__new__
Foo.__init__
After instance foo
# 'type' is implemented like following:
class type:
    def __call__(cls, *args, **kwarg):

        # A few things could possibly be done to cls here... maybe... or maybe not...
        # then we call cls.__new__() to get a new object
        obj = cls.__new__(cls, *args, **kwargs)

        # A few things done to obj here... maybe... or not...
        # then we call obj.__init__()
        obj.__init__(*args, **kwargs)

        # maybe a few more things done to obj here
        # then we return obj
        return obj

Define Final class howto

class Final(type):
    def __new__(cls, name, bases, classdict):
        for b in bases:
            if isinstance(b, Final):
                raise TypeError("type '{0}' is not an acceptable base type"
                                .format(b.__name__))
        return type.__new__(cls, name, bases, classdict)


class C(object):
    __metaclass__ = Final