## Definition

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

Python rightfully prides itself as a relatively straightforward language without a lot of "magic" hiding in its workings and features. Sometimes, however, to make interesting abstractions possible, one can dig deep in Python's more dusty and obscure corners to find language constructs that are a bit more magical than usual. Metaclasses are one such feature.

A metaclass is most commonly used as a class-factory.

## Classes are obects too

And it is possible to generate them on the fly:

def make_sample_class(**kw):
return type('DemoClass', (object,), dict(**kw))


Built-in function type produce a DemoClass blueprint. Lets compose the class itself:

sample_class = make_sample_class(a=1, b=2)
print(type(sample_class))

<class 'type'>


And now it is time to generate a particular instance:

instance = sample_class()
print(type(instance))
print("This is an instance's properties a: %s and b: %s " %
(instance.a, instance.b))

<class '__main__.DemoClass'>
... This is an instance's properties a: 1 and b: 2


## The class of a class

Every object (including built-ins) in Python has a class. We've just seen that classes are objects too, so classes must also have a class, right? Exactly. Python lets us examine the class of an object with the class attribute. Let's see this in action:

class SampleClass(object): pass

sample_object = SampleClass()
sample_object.__class__
SampleClass.__class__

>>> >>> <class '__main__.SampleClass'>
<class 'type'>


## Metaclass

A metaclass is defined as "the class of a class". Any class whose instances are themselves classes, is a metaclass. So, according to what we've seen above, this makes type a metaclass - in fact, the most commonly used metaclass in Python, since it's the default metaclass of all classes.

class Meta(object):
meta_variable = 'zero'

class ExtClass(object):
__metaclass__ = Meta
ext_variable = 'infinity'

print(ExtClass.__metaclass__)
dumb_objext = ExtClass()
print(dumb_objext.ext_variable)
print(dumb_objext.__metaclass__.meta_variable)

... >>> ... ... ... >>> >>> <class '__main__.Meta'>
>>> infinity
zero