The answer is in the priority rules for __metaclass__ search :
The corresponding metaclass is determined by the following priority rules:
- If
dict['__metaclass__'] , it is used. - Otherwise , if there is at least one base class, its metaclass is used (first it searches for the
__class__ attribute, and if it is not found, it uses its type). - Otherwise, if there is a global variable named
__metaclass__ , it is used. - Otherwise, it uses a static style, a classic metaclass (
types.ClassType ).
If we look at Foo.__class__ , we find that it is <type 'type'> , which is expected as your metaclass function, called type , to build Foo .
__class__ set by type first parameter of type.__new__ , so in the classes of the class we call type.__new__(cls, name, bases, dict) (or super(Metaclass, cls).__new__(cls, ...) ). However, we cannot do this if the metaclass is a function:
>>> def __metaclass__(name, base, dict): >>> print('inside __metaclass__(%r, %r, %r)' % (name, base, dict)) >>> return type.__new__(__metaclass__, name, base, dict) >>> class Foo(object): >>> __metaclass__ = __metaclass__ TypeError: Error when calling the metaclass bases type.__new__(X): X is not a type object (function)
Similarly, if we try to install Foo.__class__ on your __metaclass__ , this will not work, since the __class__ attribute must be a class:
>>> Foo.__class__ = Foo.__metaclass__.__func__ TypeError: __class__ must be set to new-style class, not 'function' object
So, the reason that metaclass classes that inherit from type , as opposed to just called classes, is to make them inheritable.