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.

Eli Bendersky


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:

Eli Bendersky

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.

Eli Bendersky

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

Metaclass's new and init

Metaclass's call

Examples

Trivial

string.Template

Sophisticated

Complex

Full-fledged



blog comments powered by Disqus

Published

17 December 2016

Categories

literate programming Python object-oriented-programming emacs

Tags