One might argue that such errors would be better caught by program analysis tools or
IDEs. To be sure, such tools are useful. However, if you’re creating a framework or library
that’s going to be used by others, you often don’t have any control over the rigor of their
development practices. Thus, for certain kinds of applications, it might make sense to
put a bit of extra checking in a metaclass if such checking would result in a better user
The choice of redefining __new__() or __init__() in a metaclass depends on how you
want to work with the resulting class. __new__() is invoked prior to class creation and
is typically used when a metaclass wants to alter the class definition in some way (by
changing the contents of the class dictionary). The __init__() method is invoked after
a class has been created, and is useful if you want to write code that works with the fully
formed class object. In the last example, this is essential since it is using the super()
function to search for prior definitions. This only works once the class instance has been
created and the underlying method resolution order has been set.
The last example also illustrates the use of Python’s function signature objects. Essen‐
tially, the metaclass takes each callable definition in a class, searches for a prior definition
(if any), and then simply compares their calling signatures using inspect.signature().
Last, but not least, the line of code that uses super(self, self) is not a typo. When
working with a metaclass, it’s important to realize that the self is actually a class object.
So, that statement is actually being used to find definitions located further up the class
hierarchy that make up the parents of self.
9.18. Defining Classes Programmatically
You’re writing code that ultimately needs to create a new class object. You’ve thought
about emitting emit class source code to a string and using a function such as exec()
to evaluate it, but you’d prefer a more elegant solution.
You can use the function types.new_class() to instantiate new class objects. All you
need to do is provide the name of the class, tuple of parent classes, keyword arguments,
and a callback that populates the class dictionary with members. For example:
# Example of making a class manually from parts
def __init__(self, name, shares, price):
self.name = name
370 | Chapter 9: Metaprogramming