[docs] [issue36947] [Good first issue] Fix Metaclasses Documentation

Josh Rosenberg report at bugs.python.org
Fri May 17 20:56:43 EDT 2019

Josh Rosenberg <shadowranger+python at gmail.com> added the comment:

Ah, you're right on __call__; I've never bothered to override it on a metaclass, but yes, since a class using a metaclass is an instance of the metaclass, like all instances, calling it invokes the __call__ of its type (it's just that the default metaclass, type, has a __call__ that turns around and calls the __new__ and __init__ of the "instance", which is a class). The nomenclature is hard here.

In any event, yes, overriding __call__ will let you hook into the construction of each individual instance of the classes using the metaclass. That's not generally true of all uses of metaclasses (if __call__ is inherited from type, then while new instances are technically created using the metaclass, the metaclass is just letting the normal __new__/__init__ calls take place without interference).

There is very little in the way of Python official documentation on metaclasses; the line you proposed to change is one of the few places it's mentioned (most references to metaclasses are on that Data Model page). There are a couple of mentions in the PEPs, and a lot of off-site tutorials, but it's a poorly documented feature in general.

It's pretty easy to demonstrate the current wording is correct though:

>>> class Meta(type):
...     pass
>>> class MyMeta(metaclass=Meta):
...     pass
>>> isinstance(MyMeta, Meta)

Note that we're using isinstance, not issubclass, and we're not constructing a MyMeta instance. MyMeta itself is an instance of Meta.

I really think the problem here is that the documentation is correct, but so bare it's easy to miss the implications of "MyClass and MySubclass are instances of Meta"; since the classes are instances of another class, the metaclass has the same power over them that normal classes have over their instances. That's why __call__ can hook the creation of instances, __new__ can hook the creation of the class itself, __getitem__ can be used to perform lookups on the child class (in at least of the few iterations of the typing framework, that's how List[int] and the like worked; not sure if it's still that way), and properties defined on the metaclass can be accessed on classes that use it, but not their instances. It's enormously powerful, but so complex that the Python docs tend to encourage simpler, more targeted ways of tweaking classes (e.g. decorators).


Python tracker <report at bugs.python.org>

More information about the docs mailing list