Python Metaclasses

(There is an awesome post explaining the same thing at StackOverflow; I'll try to make in shorter and more interesting.)

Why is C++ crappy as hell while Python is shining like a crown of the British Empire? Both are designed to be object-oriented languages, but the Python is the only true one. Everything in Python are objects. Literally, everything. Integers are objects, modules are objects and even object types are objects too.

Objects have constuctors. So object types have constructors too.

The built-in object-type constructor is named type and works like

mytype = type("MyTypeName", (parent1,), {'method1': lambda self: return None})

So, it takes name of the new type, tuple of parent types and dictionary of methods. That's enough to construct any class.

Yeah, it is THAT simple in Python.

type is also a class, and any standard type in Python is an instance of this class. So why not to subclass it?

To change the procedure of creating class objects (to add some auxiliary fields, for example), overload the __new__ method:

class MyType(type):
    def __new__(self, name, parents, attrs):
        # custom stuff
        return type(name, parents, attrs)

For example, here you can process fields of specific types (like Django does when handling models).

MyType, as it is a subclass of type, is called a metaclass. To create Python classes using it, specify __metaclass__ field in your classes:

class A(object):
    __metaclass__ = MyType

Customizing class creation is not the only thing possible with metaclasses.Take into account that every class born using your custom metaclass is going to be an instance of that metaclass. So you can do standard OOP things for class objects instead of class instances. For example, overload operators:

class AMaker(type):
    def __call__(self, *args, **kwargs):
        if 'please' not in kwargs:
            return "You forgot something."
        else:
            del kwargs['please']
            return super(AMaker, self).__call__(*args, **kwargs)

class A(object):
    __metaclass__ = AMaker

Operator __call__ is especially awesome, because now you can call A(...) and get different results depending on the arguments! A constructor returning objects of different types - could C++ programmers ever imagine that?