An operational explanation of Python metaclasses (part 4)
The metaclass use of __call__
that I covered in part 2 and the use of __getattribute__
et al that I
mentioned in part 3 are both specific instances of
a general metaclass power: a metaclass supplies the special methods
for its classes. However and as before, these special methods apply
only when you are looking at or manipulating the class itself, not when
you are dealing with instances of the class.
(Special methods for instances of the class have to be supplied by the class or an ancestor it inherits from, as usual.)
Most special methods aren't particularly useful for classes, since you rarely want to do things like treat a class object as a sequence; usually classes just sort of sit there being instantiated and subclassed. The useful special methods are the handful of methods that affect things that you use classes for, which means that part 2 and part 3 have already covered most of them.
(While you can define custom __str__
and __repr__
methods in
a metaclass, note that these methods are not used when printing the
class name portion of an instance of a class; you still get the familiar
'<file.whatever object at 0x...>
' result unless you have appropriate
custom methods on the class itself.)
There are two additional sets of special methods that are worth
mention. First, you can control how subclassing and instance checks
work; this is covered in the Python documentation on Customizing
instance and subclass checks,
which explicitly mentions that these methods have to be defined in
a metaclass. Second, you can use bare classes in with
statements
(instead of class instances) by implementing the context manager
special methods
on your metaclass. It's possible that there's some use for this.
Sidebar: why your metaclass must descend from type
Armed with this understanding about special methods I can now explain
the reason why metaclasses have to subclass type
instead of object
and why you get strange error messages if you don't, as I mentioned in
passing in part 1. We can see the answer by asking
'what is the metaclass of a class without a metaclass?'
The answer is 'type
'. Given that your metaclass supplies
implementations of special methods, this means that type
supplies the
default versions of things like __call__
. If you subclass type
in your metaclass, you inherit all of the necessary default versions
of various special methods. If you don't, well, they aren't going to
come from object
; object
doesn't supply them. This is also why
you need to call up to type
(either via super()
or directly) in
order to get various things done in a metaclass; type
does all of the
magic necessary to actually create new classes, call them to create new
instances of them, and so on.
(Yes, technically a metaclass can be any callable not just a class. I'm looking only at the 'metaclass as a class' case right now.)
|
|