When discussing metaclasses, the docs state:
You can of course also override other class methods (or add new methods); for example defining a custom
I thought a fleshed out Python 3 version of pyroscope's answer might be handy for someone to copy, paste and hack about with (probably me, when I find myself back at this page looking it up again in 6 months). It is taken from this article:
class Meta(type):
@classmethod
def __prepare__(mcs, name, bases, **kwargs):
print(' Meta.__prepare__(mcs=%s, name=%r, bases=%s, **%s)' % (
mcs, name, bases, kwargs
))
return {}
def __new__(mcs, name, bases, attrs, **kwargs):
print(' Meta.__new__(mcs=%s, name=%r, bases=%s, attrs=[%s], **%s)' % (
mcs, name, bases, ', '.join(attrs), kwargs
))
return super().__new__(mcs, name, bases, attrs)
def __init__(cls, name, bases, attrs, **kwargs):
print(' Meta.__init__(cls=%s, name=%r, bases=%s, attrs=[%s], **%s)' % (
cls, name, bases, ', '.join(attrs), kwargs
))
super().__init__(name, bases, attrs)
def __call__(cls, *args, **kwargs):
print(' Meta.__call__(cls=%s, args=%s, kwargs=%s)' % (
cls, args, kwargs
))
return super().__call__(*args, **kwargs)
print('** Meta class declared')
class Class(metaclass=Meta, extra=1):
def __new__(cls, myarg):
print(' Class.__new__(cls=%s, myarg=%s)' % (
cls, myarg
))
return super().__new__(cls)
def __init__(self, myarg):
print(' Class.__init__(self=%s, myarg=%s)' % (
self, myarg
))
self.myarg = myarg
super().__init__()
def __str__(self):
return "" % (
getattr(self, 'myarg', 'MISSING'),
)
print('** Class declared')
Class(1)
print('** Class instantiated')
Outputs:
** Meta class declared
Meta.__prepare__(mcs=, name='Class', bases=(), **{'extra': 1})
Meta.__new__(mcs=, name='Class', bases=(), attrs=[__module__, __qualname__, __new__, __init__, __str__, __classcell__], **{'extra': 1})
Meta.__init__(cls=, name='Class', bases=(), attrs=[__module__, __qualname__, __new__, __init__, __str__, __classcell__], **{'extra': 1})
** Class declared
Meta.__call__(cls=, args=(1,), kwargs={})
Class.__new__(cls=, myarg=1)
Class.__init__(self=, myarg=1)
** Class instantiated
Another great resource highlighted by the same article is David Beazley's PyCon 2013 Python 3 Metaprogramming tutorial.