Wandering Thoughts archives


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.)

python/UsingMetaclass04 written at 00:51:48; Add Comment

Page tools: See As Normal.
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.