classification
Title: [Good first issue] Fix 3.3.3.1 Metaclasses Documentation
Type: behavior Stage: patch review
Components: Documentation, Library (Lib) Versions: Python 3.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: docs@python Nosy List: Nicholas Matthews, codevil_2o, docs@python, josh.r, matrixise
Priority: normal Keywords: easy, patch

Created on 2019-05-17 14:27 by Nicholas Matthews, last changed 2019-08-17 07:09 by python-dev.

Pull Requests
URL Status Linked Edit
PR 15319 closed python-dev, 2019-08-17 07:09
Messages (10)
msg342723 - (view) Author: Nicholas Matthews (Nicholas Matthews) Date: 2019-05-17 14:27
Currently the final sentence of the second paragraph reads:
"In the following example, both MyClass and MySubclass are instances of Meta:"
It should read something like:
"In the following example, both MyClass and MySubclass have the metaclass Meta, and new instances will be created using Meta:"

Classes are created by their metaclass, but cannot be said to be instances of their metaclass, correct?
msg342724 - (view) Author: Stéphane Wirtel (matrixise) * (Python committer) Date: 2019-05-17 14:31
Thank you for your report
msg342725 - (view) Author: Stéphane Wirtel (matrixise) * (Python committer) Date: 2019-05-17 14:48
just one question, I don't find the paragraph with this text in the code. Could you share the link of this paragraph? Thank you
msg342726 - (view) Author: Stéphane Wirtel (matrixise) * (Python committer) Date: 2019-05-17 14:49
Found here: https://docs.python.org/3/reference/datamodel.html#metaclasses

Thank you
msg342727 - (view) Author: Stéphane Wirtel (matrixise) * (Python committer) Date: 2019-05-17 14:51
If you want to modify the text, please create a PR for this file: https://github.com/python/cpython/blob/master/Doc/reference/datamodel.rst#metaclasses

Don't forget to sign the CLA, 

Thank you
msg342728 - (view) Author: Nicholas Matthews (Nicholas Matthews) Date: 2019-05-17 14:59
Ok, I will create a PR soon and update the issue.
msg342730 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2019-05-17 15:27
Clarification is fine, but "MyClass and MySubclass are instances of Meta:" is 100% true. Declaring a class to have a metaclass (or inheriting from a class with a metaclass) means that the class itself is an instance of the metaclass.

New instances of the classes with metaclass Meta are not "created using Meta"; Meta modifies the creation of the classes themselves, not instances of the classes.

Point is, your suggested change is half wrong (new instances of MyClass and MySubclass aren't directly created using Meta), and half misunderstanding the current documentation ("MyClass is an instance of Meta" already means "MyClass has the metaclass Meta").
msg342731 - (view) Author: Nicholas Matthews (Nicholas Matthews) Date: 2019-05-17 15:35
Thanks for the clarification. For the first point on the correctness of the original text, that makes sense, could you link me to any relevant documentation for further reading?

On the second point "Meta modifies the creation of the classes themselves, not instances of the classes." I think this is not 100% correct. When you create an instance of a class via "instance = MyClass()", the `__call__` method of the metaclass is invoked, so metaclasses can control both class definition and instance creation.
msg342780 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2019-05-18 00:56
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)
True

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).
msg344105 - (view) Author: Chirag Garg (codevil_2o) Date: 2019-05-31 18:52
It should be written like "In the following example, both MyClass and MySubclass are instances of Meta and the type of MyClass is of metaclass Meta and type of MySubclass is MyClass:"
History
Date User Action Args
2019-08-17 07:09:09python-devsetkeywords: + patch
stage: patch review
pull_requests: + pull_request15037
2019-05-31 18:52:04codevil_2osetnosy: + codevil_2o
messages: + msg344105
2019-05-18 00:56:43josh.rsetmessages: + msg342780
2019-05-17 15:35:13Nicholas Matthewssetmessages: + msg342731
2019-05-17 15:27:24josh.rsetnosy: + josh.r
messages: + msg342730
2019-05-17 14:59:21Nicholas Matthewssetmessages: + msg342728
2019-05-17 14:51:04matrixisesetmessages: + msg342727
2019-05-17 14:49:42matrixisesetstatus: pending -> open

messages: + msg342726
2019-05-17 14:48:35matrixisesetstatus: open -> pending

messages: + msg342725
2019-05-17 14:38:56matrixisesetkeywords: + easy
title: Fix 3.3.3.1 Metaclasses Documentation -> [Good first issue] Fix 3.3.3.1 Metaclasses Documentation
2019-05-17 14:31:52matrixisesetnosy: + docs@python, matrixise
messages: + msg342724

assignee: docs@python
components: + Documentation
2019-05-17 14:27:51Nicholas Matthewscreate