8.5. Metaprogramming Class Factory

  • Metaclasses allow you to do 'extra things' when creating a class

  • Allow customization of class instantiation

  • Most commonly used as a class-factory

  • Registering the new class with some registry

  • Replace the class with something else entirely

  • Inject logger instance

  • Injecting static fields

  • Ensure subclass implementation

  • Metaclasses run when Python defines class (even if no instance is created)

The potential uses for metaclasses are boundless. Some ideas that have been explored include enum, logging, interface checking, automatic delegation, automatic property creation, proxies, frameworks, and automatic resource locking/synchronization. [#pydocclassobject]_

8.5.1. Recap

  • Functions are instances of a function class

Before we go into metaclasses, let's recap a fact about functions. Consider a typical function definition:

>>> def add(a, b):
...     return a + b

Functions are instances of a function class:

>>> type(add)
<class 'function'>

By extent they are effectively an instance of a type class.

8.5.2. Class Creation

  • type(str, tuple, dict) will create a class object

We need to recall how classes are created:

>>> User = type('User', (), {})

8.5.3. Function Based Metaclass

  • Metaclass is a function which returns a class

>>> def mytype(clsname, bases, attrs):
...     return type('User', (), {})

Then we can use it, instead of a regular type():

>>> User = mytype('User', (), {})

8.5.4. Usage

Function based metaclass:

>>> def mytype(clsname, bases, attrs):
...     return type('User', (), {})
>>>
>>> class User(metaclass=mytype):
...     pass

Both are equivalent and will create a class object.