Skip to content

Commit f1a54d8

Browse files
rhettingermiss-islington
authored andcommitted
bpo-45198: __set_name__ documentation not clear about its usage with non-descriptor classes (pythonGH-28439)
(cherry picked from commit 94b4626) Co-authored-by: Raymond Hettinger <[email protected]>
1 parent 6e4101a commit f1a54d8

File tree

2 files changed

+36
-30
lines changed

2 files changed

+36
-30
lines changed

Doc/reference/datamodel.rst

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1739,28 +1739,6 @@ class' :attr:`~object.__dict__`.
17391739
Called to delete the attribute on an instance *instance* of the owner class.
17401740

17411741

1742-
.. method:: object.__set_name__(self, owner, name)
1743-
1744-
Called at the time the owning class *owner* is created. The
1745-
descriptor has been assigned to *name*.
1746-
1747-
.. note::
1748-
1749-
:meth:`__set_name__` is only called implicitly as part of the
1750-
:class:`type` constructor, so it will need to be called explicitly with
1751-
the appropriate parameters when a descriptor is added to a class after
1752-
initial creation::
1753-
1754-
class A:
1755-
pass
1756-
descr = custom_descriptor()
1757-
A.attr = descr
1758-
descr.__set_name__(A, 'attr')
1759-
1760-
See :ref:`class-object-creation` for more details.
1761-
1762-
.. versionadded:: 3.6
1763-
17641742
The attribute :attr:`__objclass__` is interpreted by the :mod:`inspect` module
17651743
as specifying the class where this object was defined (setting this
17661744
appropriately can assist in runtime introspection of dynamic class attributes).
@@ -1949,6 +1927,33 @@ class defining the method.
19491927
.. versionadded:: 3.6
19501928

19511929

1930+
When a class is created, :meth:`type.__new__` scans the class variables
1931+
and makes callbacks to those with a :meth:`__set_name__` hook.
1932+
1933+
.. method:: object.__set_name__(self, owner, name)
1934+
1935+
Automatically called at the time the owning class *owner* is
1936+
created. The object has been assigned to *name* in that class::
1937+
1938+
class A:
1939+
x = C() # Automatically calls: x.__set_name__(A, 'x')
1940+
1941+
If the class variable is assigned after the class is created,
1942+
:meth:`__set_name__` will not be called automatically.
1943+
If needed, :meth:`__set_name__` can be called directly::
1944+
1945+
class A:
1946+
pass
1947+
1948+
c = C()
1949+
A.x = c # The hook is not called
1950+
c.__set_name__(A, 'x') # Manually invoke the hook
1951+
1952+
See :ref:`class-object-creation` for more details.
1953+
1954+
.. versionadded:: 3.6
1955+
1956+
19521957
.. _metaclasses:
19531958

19541959
Metaclasses
@@ -2098,15 +2103,15 @@ current call is identified based on the first argument passed to the method.
20982103
Failing to do so will result in a :exc:`RuntimeError` in Python 3.8.
20992104

21002105
When using the default metaclass :class:`type`, or any metaclass that ultimately
2101-
calls ``type.__new__``, the following additional customisation steps are
2106+
calls ``type.__new__``, the following additional customization steps are
21022107
invoked after creating the class object:
21032108

2104-
* first, ``type.__new__`` collects all of the descriptors in the class
2105-
namespace that define a :meth:`~object.__set_name__` method;
2106-
* second, all of these ``__set_name__`` methods are called with the class
2107-
being defined and the assigned name of that particular descriptor;
2108-
* finally, the :meth:`~object.__init_subclass__` hook is called on the
2109-
immediate parent of the new class in its method resolution order.
2109+
1) The ``type.__new__`` method collects all of the attributes in the class
2110+
namespace that define a :meth:`~object.__set_name__` method;
2111+
2) Those ``__set_name__`` methods are called with the class
2112+
being defined and the assigned name of that particular attribute;
2113+
3) The :meth:`~object.__init_subclass__` hook is called on the
2114+
immediate parent of the new class in its method resolution order.
21102115

21112116
After the class object is created, it is passed to the class decorators
21122117
included in the class definition (if any) and the resulting object is bound

Objects/typeobject.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8428,7 +8428,8 @@ update_all_slots(PyTypeObject* type)
84288428
}
84298429

84308430

8431-
/* Call __set_name__ on all descriptors in a newly generated type */
8431+
/* Call __set_name__ on all attributes (including descriptors)
8432+
in a newly generated type */
84328433
static int
84338434
type_new_set_names(PyTypeObject *type)
84348435
{

0 commit comments

Comments
 (0)