What is a metaclass in Python?


What are metaclasses? What do you use them for?


Answers



A metaclass is the class of a class. Like a class defines how an instance of the class behaves, a metaclass defines how a class behaves. A class is an instance of a metaclass.

While in Python you can use arbitrary callables for metaclasses (like Jerub shows), the more useful approach is actually to make it an actual class itself. type is the usual metaclass in Python. In case you're wondering, yes, type is itself a class, and it is its own type. You won't be able to recreate something like type purely in Python, but Python cheats a little. To create your own metaclass in Python you really just want to subclass type.

A metaclass is most commonly used as a class-factory. Like you create an instance of the class by calling the class, Python creates a new class (when it executes the 'class' statement) by calling the metaclass. Combined with the normal __init__ and __new__ methods, metaclasses therefore allow you to do 'extra things' when creating a class, like registering the new class with some registry, or even replace the class with something else entirely.

When the class statement is executed, Python first executes the body of the class statement as a normal block of code. The resulting namespace (a dict) holds the attributes of the class-to-be. The metaclass is determined by looking at the baseclasses of the class-to-be (metaclasses are inherited), at the __metaclass__ attribute of the class-to-be (if any) or the __metaclass__ global variable. The metaclass is then called with the name, bases and attributes of the class to instantiate it.

However, metaclasses actually define the type of a class, not just a factory for it, so you can do much more with them. You can, for instance, define normal methods on the metaclass. These metaclass-methods are like classmethods, in that they can be called on the class without an instance, but they are also not like classmethods in that they cannot be called on an instance of the class. type.__subclasses__() is an example of a method on the type metaclass. You can also define the normal 'magic' methods, like __add__, __iter__ and __getattr__, to implement or change how the class behaves.

Here's an aggregated example of the bits and pieces:

def make_hook(f):
    """Decorator to turn 'foo' method into '__foo__'"""
    f.is_hook = 1
    return f

class MyType(type):
    def __new__(cls, name, bases, attrs):

        if name.startswith('None'):
            return None

        # Go over attributes and see if they should be renamed.
        newattrs = {}
        for attrname, attrvalue in attrs.iteritems():
            if getattr(attrvalue, 'is_hook', 0):
                newattrs['__%s__' % attrname] = attrvalue
            else:
                newattrs[attrname] = attrvalue

        return super(MyType, cls).__new__(cls, name, bases, newattrs)

    def __init__(self, name, bases, attrs):
        super(MyType, self).__init__(name, bases, attrs)

        # classregistry.register(self, self.interfaces)
        print "Would register class %s now." % self

    def __add__(self, other):
        class AutoClass(self, other):
            pass
        return AutoClass
        # Alternatively, to autogenerate the classname as well as the class:
        # return type(self.__name__ + other.__name__, (self, other), {})

    def unregister(self):
        # classregistry.unregister(self)
        print "Would unregister class %s now." % self

class MyObject:
    __metaclass__ = MyType


class NoneSample(MyObject):
    pass

# Will print "NoneType None"
print type(NoneSample), repr(NoneSample)

class Example(MyObject):
    def __init__(self, value):
        self.value = value
    @make_hook
    def add(self, other):
        return self.__class__(self.value + other.value)

# Will unregister the class
Example.unregister()

inst = Example(10)
# Will fail with an AttributeError
#inst.unregister()

print inst + inst
class Sibling(MyObject):
    pass

ExampleSibling = Example + Sibling
# ExampleSibling is now a subclass of both Example and Sibling (with no
# content of its own) although it will believe it's called 'AutoClass'
print ExampleSibling
print ExampleSibling.__mro__



Classes as objects

Before understanding metaclasses, you need to master classes in Python. And Python has a very peculiar idea of what classes are, borrowed from the Smalltalk language.

In most languages, classes are just pieces of code that describe how to produce an object. That's kinda true in Python too:

>>> class ObjectCreator(object):
...       pass
... 

>>> my_object = ObjectCreator()
>>> print(my_object)
<__main__.ObjectCreator object at 0x8974f2c>

But classes are more than that in Python. Classes are objects too.

Yes, objects.

As soon as you use the keyword class, Python executes it and creates an OBJECT. The instruction

>>> class ObjectCreator(object):
...       pass
... 

creates in memory an object with the name "ObjectCreator".

This object (the class) is itself capable of creating objects (the instances), and this is why it's a class.

But still, it's an object, and therefore:

  • you can assign it to a variable
  • you can copy it
  • you can add attributes to it
  • you can pass it as a function parameter

e.g.:

>>> print(ObjectCreator) # you can print a class because it's an object
<class '__main__.ObjectCreator'>
>>> def echo(o):
...       print(o)
... 
>>> echo(ObjectCreator) # you can pass a class as a parameter
<class '__main__.ObjectCreator'>
>>> print(hasattr(ObjectCreator, 'new_attribute'))
False
>>> ObjectCreator.new_attribute = 'foo' # you can add attributes to a class
>>> print(hasattr(ObjectCreator, 'new_attribute'))
True
>>> print(ObjectCreator.new_attribute)
foo
>>> ObjectCreatorMirror = ObjectCreator # you can assign a class to a variable
>>> print(ObjectCreatorMirror.new_attribute)
foo
>>> print(ObjectCreatorMirror())
<__main__.ObjectCreator object at 0x8997b4c>

Creating classes dynamically

Since classes are objects, you can create them on the fly, like any object.

First, you can create a class in a function using class:

>>> def choose_class(name):
...     if name == 'foo':
...         class Foo(object):
...             pass
...         return Foo # return the class, not an instance
...     else:
...         class Bar(object):
...             pass
...         return Bar
...     
>>> MyClass = choose_class('foo') 
>>> print(MyClass) # the function returns a class, not an instance
<class '__main__.Foo'>
>>> print(MyClass()) # you can create an object from this class
<__main__.Foo object at 0x89c6d4c>

But it's not so dynamic, since you still have to write the whole class yourself.

Since classes are objects, they must be generated by something.

When you use the class keyword, Python creates this object automatically. But as with most things in Python, it gives you a way to do it manually.

Remember the function type? The good old function that lets you know what type an object is:

>>> print(type(1))
<type 'int'>
>>> print(type("1"))
<type 'str'>
>>> print(type(ObjectCreator))
<type 'type'>
>>> print(type(ObjectCreator()))
<class '__main__.ObjectCreator'>

Well, type has a completely different ability, it can also create classes on the fly. type can take the description of a class as parameters, and return a class.

(I know, it's silly that the same function can have two completely different uses according to the parameters you pass to it. It's an issue due to backwards compatibility in Python)

type works this way:

type(name of the class, 
     tuple of the parent class (for inheritance, can be empty), 
     dictionary containing attributes names and values)

e.g.:

>>> class MyShinyClass(object):
...       pass

can be created manually this way:

>>> MyShinyClass = type('MyShinyClass', (), {}) # returns a class object
>>> print(MyShinyClass)
<class '__main__.MyShinyClass'>
>>> print(MyShinyClass()) # create an instance with the class
<__main__.MyShinyClass object at 0x8997cec>

You'll notice that we use "MyShinyClass" as the name of the class and as the variable to hold the class reference. They can be different, but there is no reason to complicate things.

type accepts a dictionary to define the attributes of the class. So:

>>> class Foo(object):
...       bar = True

Can be translated to:

>>> Foo = type('Foo', (), {'bar':True})

And used as a normal class:

>>> print(Foo)
<class '__main__.Foo'>
>>> print(Foo.bar)
True
>>> f = Foo()
>>> print(f)
<__main__.Foo object at 0x8a9b84c>
>>> print(f.bar)
True

And of course, you can inherit from it, so:

>>>   class FooChild(Foo):
...         pass

would be:

>>> FooChild = type('FooChild', (Foo,), {})
>>> print(FooChild)
<class '__main__.FooChild'>
>>> print(FooChild.bar) # bar is inherited from Foo
True

Eventually you'll want to add methods to your class. Just define a function with the proper signature and assign it as an attribute.

>>> def echo_bar(self):
...       print(self.bar)
... 
>>> FooChild = type('FooChild', (Foo,), {'echo_bar': echo_bar})
>>> hasattr(Foo, 'echo_bar')
False
>>> hasattr(FooChild, 'echo_bar')
True
>>> my_foo = FooChild()
>>> my_foo.echo_bar()
True

And you can add even more methods after you dynamically create the class, just like adding methods to a normally created class object.

>>> def echo_bar_more(self):
...       print('yet another method')
... 
>>> FooChild.echo_bar_more = echo_bar_more
>>> hasattr(FooChild, 'echo_bar_more')
True

You see where we are going: in Python, classes are objects, and you can create a class on the fly, dynamically.

This is what Python does when you use the keyword class, and it does so by using a metaclass.

What are metaclasses (finally)

Metaclasses are the 'stuff' that creates classes.

You define classes in order to create objects, right?

But we learned that Python classes are objects.

Well, metaclasses are what create these objects. They are the classes' classes, you can picture them this way:

MyClass = MetaClass()
MyObject = MyClass()

You've seen that type lets you do something like this:

MyClass = type('MyClass', (), {})

It's because the function type is in fact a metaclass. type is the metaclass Python uses to create all classes behind the scenes.

Now you wonder why the heck is it written in lowercase, and not Type?

Well, I guess it's a matter of consistency with str, the class that creates strings objects, and int the class that creates integer objects. type is just the class that creates class objects.

You see that by checking the __class__ attribute.

Everything, and I mean everything, is an object in Python. That includes ints, strings, functions and classes. All of them are objects. And all of them have been created from a class:

>>> age = 35
>>> age.__class__
<type 'int'>
>>> name = 'bob'
>>> name.__class__
<type 'str'>
>>> def foo(): pass
>>> foo.__class__
<type 'function'>
>>> class Bar(object): pass
>>> b = Bar()
>>> b.__class__
<class '__main__.Bar'>

Now, what is the __class__ of any __class__ ?

>>> age.__class__.__class__
<type 'type'>
>>> name.__class__.__class__
<type 'type'>
>>> foo.__class__.__class__
<type 'type'>
>>> b.__class__.__class__
<type 'type'>

So, a metaclass is just the stuff that creates class objects.

You can call it a 'class factory' if you wish.

type is the built-in metaclass Python uses, but of course, you can create your own metaclass.

The __metaclass__ attribute

You can add a __metaclass__ attribute when you write a class:

class Foo(object):
  __metaclass__ = something...
  [...]

If you do so, Python will use the metaclass to create the class Foo.

Careful, it's tricky.

You write class Foo(object) first, but the class object Foo is not created in memory yet.

Python will look for __metaclass__ in the class definition. If it finds it, it will use it to create the object class Foo. If it doesn't, it will use type to create the class.

Read that several times.

When you do:

class Foo(Bar):
  pass

Python does the following:

Is there a __metaclass__ attribute in Foo?

If yes, create in memory a class object (I said a class object, stay with me here), with the name Foo by using what is in __metaclass__.

If Python can't find __metaclass__, it will look for a __metaclass__ at the MODULE level, and try to do the same (but only for classes that don't inherit anything, basically old-style classes).

Then if it can't find any __metaclass__ at all, it will use the Bar's (the first parent) own metaclass (which might be the default type) to create the class object.

Be careful here that the __metaclass__ attribute will not be inherited, the metaclass of the parent (Bar.__class__) will be. If Bar used a __metaclass__ attribute that created Bar with type() (and not type.__new__()), the subclasses will not inherit that behavior.

Now the big question is, what can you put in __metaclass__ ?

The answer is: something that can create a class.

And what can create a class? type, or anything that subclasses or uses it.

Custom metaclasses

The main purpose of a metaclass is to change the class automatically, when it's created.

You usually do this for APIs, where you want to create classes matching the current context.

Imagine a stupid example, where you decide that all classes in your module should have their attributes written in uppercase. There are several ways to do this, but one way is to set __metaclass__ at the module level.

This way, all classes of this module will be created using this metaclass, and we just have to tell the metaclass to turn all attributes to uppercase.

Luckily, __metaclass__ can actually be any callable, it doesn't need to be a formal class (I know, something with 'class' in its name doesn't need to be a class, go figure... but it's helpful).

So we will start with a simple example, by using a function.

# the metaclass will automatically get passed the same argument
# that you usually pass to `type`
def upper_attr(future_class_name, future_class_parents, future_class_attr):
  """
    Return a class object, with the list of its attribute turned 
    into uppercase.
  """

  # pick up any attribute that doesn't start with '__' and uppercase it
  uppercase_attr = {}
  for name, val in future_class_attr.items():
      if not name.startswith('__'):
          uppercase_attr[name.upper()] = val
      else:
          uppercase_attr[name] = val

  # let `type` do the class creation
  return type(future_class_name, future_class_parents, uppercase_attr)

__metaclass__ = upper_attr # this will affect all classes in the module

class Foo(): # global __metaclass__ won't work with "object" though
  # but we can define __metaclass__ here instead to affect only this class
  # and this will work with "object" children
  bar = 'bip'

print(hasattr(Foo, 'bar'))
# Out: False
print(hasattr(Foo, 'BAR'))
# Out: True

f = Foo()
print(f.BAR)
# Out: 'bip'

Now, let's do exactly the same, but using a real class for a metaclass:

# remember that `type` is actually a class like `str` and `int`
# so you can inherit from it
class UpperAttrMetaclass(type): 
    # __new__ is the method called before __init__
    # it's the method that creates the object and returns it
    # while __init__ just initializes the object passed as parameter
    # you rarely use __new__, except when you want to control how the object
    # is created.
    # here the created object is the class, and we want to customize it
    # so we override __new__
    # you can do some stuff in __init__ too if you wish
    # some advanced use involves overriding __call__ as well, but we won't
    # see this
    def __new__(upperattr_metaclass, future_class_name, 
                future_class_parents, future_class_attr):

        uppercase_attr = {}
        for name, val in future_class_attr.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val

        return type(future_class_name, future_class_parents, uppercase_attr)

But this is not really OOP. We call type directly and we don't override or call the parent __new__. Let's do it:

class UpperAttrMetaclass(type): 

    def __new__(upperattr_metaclass, future_class_name, 
                future_class_parents, future_class_attr):

        uppercase_attr = {}
        for name, val in future_class_attr.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val

        # reuse the type.__new__ method
        # this is basic OOP, nothing magic in there
        return type.__new__(upperattr_metaclass, future_class_name, 
                            future_class_parents, uppercase_attr)

You may have noticed the extra argument upperattr_metaclass. There is nothing special about it: __new__ always receives the class it's defined in, as first parameter. Just like you have self for ordinary methods which receive the instance as first parameter, or the defining class for class methods.

Of course, the names I used here are long for the sake of clarity, but like for self, all the arguments have conventional names. So a real production metaclass would look like this:

class UpperAttrMetaclass(type): 

    def __new__(cls, clsname, bases, dct):

        uppercase_attr = {}
        for name, val in dct.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val

        return type.__new__(cls, clsname, bases, uppercase_attr)

We can make it even cleaner by using super, which will ease inheritance (because yes, you can have metaclasses, inheriting from metaclasses, inheriting from type):

class UpperAttrMetaclass(type): 

    def __new__(cls, clsname, bases, dct):

        uppercase_attr = {}
        for name, val in dct.items():
            if not name.startswith('__'):
                uppercase_attr[name.upper()] = val
            else:
                uppercase_attr[name] = val

        return super(UpperAttrMetaclass, cls).__new__(cls, clsname, bases, uppercase_attr)

That's it. There is really nothing more about metaclasses.

The reason behind the complexity of the code using metaclasses is not because of metaclasses, it's because you usually use metaclasses to do twisted stuff relying on introspection, manipulating inheritance, vars such as __dict__, etc.

Indeed, metaclasses are especially useful to do black magic, and therefore complicated stuff. But by themselves, they are simple:

  • intercept a class creation
  • modify the class
  • return the modified class

Why would you use metaclasses classes instead of functions?

Since __metaclass__ can accept any callable, why would you use a class since it's obviously more complicated?

There are several reasons to do so:

  • The intention is clear. When you read UpperAttrMetaclass(type), you know what's going to follow
  • You can use OOP. Metaclass can inherit from metaclass, override parent methods. Metaclasses can even use metaclasses.
  • Children of a class will be instances of its metaclass if you specified a metaclass-class, but not with a metaclass-function.
  • You can structure your code better. You never use metaclasses for something as trivial as the above example. It's usually for something complicated. Having the ability to make several methods and group them in one class is very useful to make the code easier to read.
  • You can hook on __new__, __init__ and __call__. Which will allow you to do different stuff. Even if usually you can do it all in __new__, some people are just more comfortable using __init__.
  • These are called metaclasses, damn it! It must mean something!

Why would you use metaclasses?

Now the big question. Why would you use some obscure error prone feature?

Well, usually you don't:

Metaclasses are deeper magic that 99% of users should never worry about. If you wonder whether you need them, you don't (the people who actually need them know with certainty that they need them, and don't need an explanation about why).

Python Guru Tim Peters

The main use case for a metaclass is creating an API. A typical example of this is the Django ORM.

It allows you to define something like this:

class Person(models.Model):
  name = models.CharField(max_length=30)
  age = models.IntegerField()

But if you do this:

guy = Person(name='bob', age='35')
print(guy.age)

It won't return an IntegerField object. It will return an int, and can even take it directly from the database.

This is possible because models.Model defines __metaclass__ and it uses some magic that will turn the Person you just defined with simple statements into a complex hook to a database field.

Django makes something complex look simple by exposing a simple API and using metaclasses, recreating code from this API to do the real job behind the scenes.

The last word

First, you know that classes are objects that can create instances.

Well in fact, classes are themselves instances. Of metaclasses.

>>> class Foo(object): pass
>>> id(Foo)
142630324

Everything is an object in Python, and they are all either instances of classes or instances of metaclasses.

Except for type.

type is actually its own metaclass. This is not something you could reproduce in pure Python, and is done by cheating a little bit at the implementation level.

Secondly, metaclasses are complicated. You may not want to use them for very simple class alterations. You can change classes by using two different techniques:

99% of the time you need class alteration, you are better off using these.

But 98% of the time, you don't need class alteration at all.




Note, this answer is for Python 2.x as it was written in 2008, metaclasses are slightly different in 3.x, see the comments.

Metaclasses are the secret sauce that make 'class' work. The default metaclass for a new style object is called 'type'.

class type(object)
  |  type(object) -> the object's type
  |  type(name, bases, dict) -> a new type

Metaclasses take 3 args. 'name', 'bases' and 'dict'

Here is where the secret starts. Look for where name, bases and the dict come from in this example class definition.

class ThisIsTheName(Bases, Are, Here):
    All_the_code_here
    def doesIs(create, a):
        dict

Lets define a metaclass that will demonstrate how 'class:' calls it.

def test_metaclass(name, bases, dict):
    print 'The Class Name is', name
    print 'The Class Bases are', bases
    print 'The dict has', len(dict), 'elems, the keys are', dict.keys()

    return "yellow"

class TestName(object, None, int, 1):
    __metaclass__ = test_metaclass
    foo = 1
    def baz(self, arr):
        pass

print 'TestName = ', repr(TestName)

# output => 
The Class Name is TestName
The Class Bases are (<type 'object'>, None, <type 'int'>, 1)
The dict has 4 elems, the keys are ['baz', '__module__', 'foo', '__metaclass__']
TestName =  'yellow'

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

Note that the magic behaviour that 'Initalised' gains by having the metaclass init_attributes is not passed onto a subclass of Initalised.

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



Python: Run code when a class is subclassed

Classes (by default) are instances of type. Just as an instance of a class Foo is created by foo = Foo(...), an instance of type (i.e. a class) is created by myclass = type(name, bases, clsdict).

If you want something special to happen at the moment of class-creation, then you have to modify the thing creating the class -- i.e. type. The way to do that is to define a subclass of type -- i.e. a metaclass.

A metaclass is to its class as a class is to its instance.

In Python2 you would define the metaclass of a class with

class SuperClass:
    __metaclass__ = Watcher

where Watcher is a subclass of type.

In Python3 the syntax has been changed to

class SuperClass(metaclass=Watcher)

Both are equivalent to

Superclass = Watcher(name, bases, clsdict)

where in this case, name equals the string 'Superclass', and bases is the tuple (object, ). The clsdict is a dictionary of the class attributes defined in the body of the class definition.

Note the similarity to myclass = type(name, bases, clsdict).

So, just as you would use a class's __init__ to control events at the moment of a instance's creation, you can control events at the moment of a class's creation with a metaclass's __init__:


class Watcher(type):
    def __init__(cls, name, bases, clsdict):
        if len(cls.mro()) > 2:
            print("was subclassed by " + name)
        super(Watcher, cls).__init__(name, bases, clsdict)

class SuperClass:
    __metaclass__ = Watcher


print("foo")

class SubClass0(SuperClass):
  pass

print("bar")

class SubClass1(SuperClass):
  print("test")

prints

foo
was subclassed by SubClass0
bar
test
was subclassed by SubClass1



Edit: My old post actually didn't work. Subclassing from classmethod doesn't work as expected.

First, we would like to have some way to tell the metaclass that this particular method is supposed to have the special called on subclass behavior, we'll just set an attribute on the function we'd like to call. As a convenience, we'll even turn the function into a classmethod so that the real baseclass it was found in can be discovered, too. We'll return the classmethod so that it can be used as a decorator, which is most convenient.

import types
import inspect

def subclass_hook(func):
    func.is_subclass_hook = True
    return classmethod(func)

We're also going to want a convenient way to see that the subclass_hook decorator was used. We know that classmethod has been used, so we'll check for that, and only then look for the is_subclass_hook attribute.

def test_subclass_hook(thing):
    x = (isinstance(thing, types.MethodType) and
         getattr(thing.im_func, 'is_subclass_hook', False))
    return x

Finally, we need a metaclass that acts on the information: For most cases, the most interesting thing to do here is just check each of the supplied bases for hooks. In that way, super works in the least surprising way.

class MyMetaclass(type):
    def __init__(cls, name, bases, attrs):
        super(MyMetaclass, cls).__init__(name, bases, attrs)

        for base in bases:
            if base is object:
                continue
            for name, hook in inspect.getmembers(base, test_subclass_hook):
                hook(cls)

and that should do it.

>>> class SuperClass:
...     __metaclass__ = MyMetaclass
...     @subclass_hook
...     def triggered_routine(cls, subclass):
...         print(cls.__name__ + " was subclassed by " + subclass.__name__)

>>> class SubClass0(SuperClass):
...     pass
SuperClass was subclassed by SubClass0

>>> class SubClass1(SuperClass):
...     print("test")
test
SuperClass was subclassed by SubClass1



Understanding metaclass and inheritance in Python

1) what is use of metaclass and when to use it?

Metaclasses are to classes as classes are to objects. They are classes for classes (hence the expression "meta").

Metaclasses are typically for when you want to work outside of the normal constraints of OOP.

2) what is difference/similarity between metaclass and inheritance?

A metaclass is not part of an object's class hierarchy whereas base classes are. So when an object does "obj.some_method()" it will not search the metaclass for this method however the metaclass may have created it during the class' or object's creation.

In this example below, the metaclass meta_car gives objects a "defect" attribute based on a random number. The "defect" attribute is not defined in any of the objects' base classes or the class itself. This, however, could have been achieved using classes only.

However (unlike classes), this metaclass also re-routes object creation; in the some_cars list, all the Toyotas are created using the Car class. The metaclass detects that a Car __init__ contains a make argument that matches a pre-existing class by that name and so returns a object of that class instead.

Additionally, you'll also note that in the some_cars list, a Car __init__ is called with make="GM". A GM class has not been defined at this point in the program's evaluation. The metaclass detects that a class doesn't exist by that name in the make argument, so it creates one and updates the global namespace (so it doesn't need to use the return mechanism). It then creates the object using the newly defined class and returns it.

import random

class CarBase(object):
    pass

class meta_car(type):
    car_brands = {}
    def __init__(cls, cls_name, cls_bases, cls_dict):
        super(meta_car, cls).__init__(cls_name, cls_bases, cls_dict)
        if(not CarBase in cls_bases):
            meta_car.car_brands[cls_name] = cls

    def __call__(self, *args, **kwargs):
        make = kwargs.get("make", "")
        if(meta_car.car_brands.has_key(make) and not (self is meta_car.car_brands[make])):
            obj = meta_car.car_brands[make].__call__(*args, **kwargs)
            if(make == "Toyota"):
                if(random.randint(0, 100) < 2):
                    obj.defect = "sticky accelerator pedal"
            elif(make == "GM"):
                if(random.randint(0, 100) < 20):
                    obj.defect = "shithouse"
            elif(make == "Great Wall"):
                if(random.randint(0, 100) < 101):
                    obj.defect = "cancer"
        else:
            obj = None
            if(not meta_car.car_brands.has_key(self.__name__)):
                new_class = meta_car(make, (GenericCar,), {})
                globals()[make] = new_class
                obj = new_class(*args, **kwargs)
            else:
                obj = super(meta_car, self).__call__(*args, **kwargs)
        return obj

class Car(CarBase):
    __metaclass__ = meta_car

    def __init__(self, **kwargs):
        for name, value in kwargs.items():
            setattr(self, name, value)

    def __repr__(self):
        return "<%s>" % self.description

    @property
    def description(self):           
        return "%s %s %s %s" % (self.color, self.year, self.make, self.model)

class GenericCar(Car):
    def __init__(self, **kwargs):
        kwargs["make"] = self.__class__.__name__
        super(GenericCar, self).__init__(**kwargs)

class Toyota(GenericCar):
    pass

colours = \
[
    "blue",
    "green",
    "red",
    "yellow",
    "orange",
    "purple",
    "silver",
    "black",
    "white"
]

def rand_colour():
    return colours[random.randint(0, len(colours) - 1)]

some_cars = \
[
    Car(make="Toyota", model="Prius", year=2005, color=rand_colour()),
    Car(make="Toyota", model="Camry", year=2007, color=rand_colour()),
    Car(make="Toyota", model="Camry Hybrid", year=2013, color=rand_colour()),
    Car(make="Toyota", model="Land Cruiser", year=2009, color=rand_colour()),
    Car(make="Toyota", model="FJ Cruiser", year=2012, color=rand_colour()),
    Car(make="Toyota", model="Corolla", year=2010, color=rand_colour()),
    Car(make="Toyota", model="Hiace", year=2006, color=rand_colour()),
    Car(make="Toyota", model="Townace", year=2003, color=rand_colour()),
    Car(make="Toyota", model="Aurion", year=2008, color=rand_colour()),
    Car(make="Toyota", model="Supra", year=2004, color=rand_colour()),
    Car(make="Toyota", model="86", year=2013, color=rand_colour()),
    Car(make="GM", model="Camaro", year=2008, color=rand_colour())
]

dodgy_vehicles = filter(lambda x: hasattr(x, "defect"), some_cars)
print dodgy_vehicles

3) where should one use metaclass or inheritance?

As mentioned in this answer and in the comments, almost always use inheritance when doing OOP. Metaclasses are for working outside those constraints (refer to example) and is almost always not necessary however some very advanced and extremely dynamic program flow can be achieved with them. This is both their strength and their danger.




What is the difference between a 'Type' and an 'Object' in Python

Python's super function does different things depending on what it's arguments are. Here's a demonstration of different ways of using it:

class Base(object):
    def __init__(self, val):
        self.val = val

    @classmethod
    def make_obj(cls, val):
        return cls(val+1)

class Derived(Base):
    def __init__(self, val):
        # In this super call, the second argument "self" is an object.
        # The result acts like an object of the Base class.
        super(Derived, self).__init__(val+2)

    @classmethod
    def make_obj(cls, val):
        # In this super call, the second argument "cls" is a type.
        # The result acts like the Base class itself.
        return super(Derived, cls).make_obj(val)

Test output:

>>> b1 = Base(0)
>>> b1.val
0
>>> b2 = Base.make_obj(0)
>>> b2.val
1
>>> d1 = Derived(0)
>>> d1.val
2
>>> d2 = Derived.make_obj(0)
>>> d2.val
3

The 3 result is the combination of the previous modifiers: 1 (from Base.make_obj) plus 2 (from Derived.__init__).

Note that it is possible to call super with just one argument to get an "unbound" super object, it is apparently not useful for much. There's not really any reason to do this unless you want to mess around with Python internals and you really know what you're doing.

In Python 3, you can also call super with no arguments (which is equivalent to providing the current class and self as two arguments, but more magical).




Object can be any Python class instance which may or may not be user defined. But, when you are talking about a type, it refers to the default objects/collections like a list/tuple/dict/int/str etc.




Here is a simple exploration of the two functions. I found it illuminating going through this exercise. I often will create a simple program exploring the ins and outs of simple functions and save them for reference:

#
# Testing isinstance and issubclass
#

class C1(object):
    def __init__(self):
        object.__init__(self)

class B1(object):
    def __init__(self):
        object.__init__(self)

class B2(B1):
    def __init__(self):
        B1.__init__(self)

class CB1(C1,B1):
    def __init__(self):
        # not sure about this for multiple inheritance
        C1.__init__(self)
        B1.__init__(self)

c1 = C1()
b1 = B1()
cb1 = CB1()

def checkInstanceType(c, t):
    if isinstance(c, t):
        print c, "is of type", t
    else:
        print c, "is NOT of type", t

def checkSubclassType(c, t):
    if issubclass(c, t):
        print c, "is a subclass of type", t
    else:
        print c, "is NOT a subclass of type", t

print "comparing isinstance and issubclass"
print ""

# checking isinstance
print "checking isinstance"

# can check instance against type
checkInstanceType(c1, C1)
checkInstanceType(c1, B1)
checkInstanceType(c1, object)

# can check type against type
checkInstanceType(C1, object)
checkInstanceType(B1, object)

# cannot check instance against instance
try:
    checkInstanceType(c1, b1)
except Exception, e:
    print "failed to check instance against instance", e

print ""

# checking issubclass
print "checking issubclass"

# cannot check instance against type
try:
    checkSubclassType(c1, C1)
except Exception, e:
    print "failed to check instance against type", e

# can check type against type
checkSubclassType(C1, C1)
checkSubclassType(B1, C1)
checkSubclassType(CB1, C1)
checkSubclassType(CB1, B1)

# cannot check type against instance
try:
    checkSubclassType(C1, c1)
except Exception, e:
    print "failed to check type against instance", e

Edit: Also consider the following as isinstance can break API implementations. An example would be an object that acts like a dictionary, but is not derived from dict. isinstance might check that an object is a dictionary, even though the object supports dictionary style access: isinstance considered harmful

Edit2:

Can someone please give me an example of a distinction between passing a Type as a second argument versus passing an Object?

After testing the above code it tells me the second parameter must be a type. So in the following case:

checkInstanceType(c1, b1)

The call will fail. It could be written:

checkInstanceType(c1, type(b1))

So if you want to check the type of one instance against another instance you have to use the type() builtin call.