Skip to content

Commit 94b4626

Browse files
authored
bpo-45198: __set_name__ documentation not clear about its usage with non-descriptor classes (GH-28439)
1 parent a6e8db5 commit 94b4626

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
@@ -1774,28 +1774,6 @@ class' :attr:`~object.__dict__`.
17741774
Called to delete the attribute on an instance *instance* of the owner class.
17751775

17761776

1777-
.. method:: object.__set_name__(self, owner, name)
1778-
1779-
Called at the time the owning class *owner* is created. The
1780-
descriptor has been assigned to *name*.
1781-
1782-
.. note::
1783-
1784-
:meth:`__set_name__` is only called implicitly as part of the
1785-
:class:`type` constructor, so it will need to be called explicitly with
1786-
the appropriate parameters when a descriptor is added to a class after
1787-
initial creation::
1788-
1789-
class A:
1790-
pass
1791-
descr = custom_descriptor()
1792-
A.attr = descr
1793-
descr.__set_name__(A, 'attr')
1794-
1795-
See :ref:`class-object-creation` for more details.
1796-
1797-
.. versionadded:: 3.6
1798-
17991777
The attribute :attr:`__objclass__` is interpreted by the :mod:`inspect` module
18001778
as specifying the class where this object was defined (setting this
18011779
appropriately can assist in runtime introspection of dynamic class attributes).
@@ -1984,6 +1962,33 @@ class defining the method.
19841962
.. versionadded:: 3.6
19851963

19861964

1965+
When a class is created, :meth:`type.__new__` scans the class variables
1966+
and makes callbacks to those with a :meth:`__set_name__` hook.
1967+
1968+
.. method:: object.__set_name__(self, owner, name)
1969+
1970+
Automatically called at the time the owning class *owner* is
1971+
created. The object has been assigned to *name* in that class::
1972+
1973+
class A:
1974+
x = C() # Automatically calls: x.__set_name__(A, 'x')
1975+
1976+
If the class variable is assigned after the class is created,
1977+
:meth:`__set_name__` will not be called automatically.
1978+
If needed, :meth:`__set_name__` can be called directly::
1979+
1980+
class A:
1981+
pass
1982+
1983+
c = C()
1984+
A.x = c # The hook is not called
1985+
c.__set_name__(A, 'x') # Manually invoke the hook
1986+
1987+
See :ref:`class-object-creation` for more details.
1988+
1989+
.. versionadded:: 3.6
1990+
1991+
19871992
.. _metaclasses:
19881993

19891994
Metaclasses
@@ -2133,15 +2138,15 @@ current call is identified based on the first argument passed to the method.
21332138
Failing to do so will result in a :exc:`RuntimeError` in Python 3.8.
21342139

21352140
When using the default metaclass :class:`type`, or any metaclass that ultimately
2136-
calls ``type.__new__``, the following additional customisation steps are
2141+
calls ``type.__new__``, the following additional customization steps are
21372142
invoked after creating the class object:
21382143

2139-
* first, ``type.__new__`` collects all of the descriptors in the class
2140-
namespace that define a :meth:`~object.__set_name__` method;
2141-
* second, all of these ``__set_name__`` methods are called with the class
2142-
being defined and the assigned name of that particular descriptor;
2143-
* finally, the :meth:`~object.__init_subclass__` hook is called on the
2144-
immediate parent of the new class in its method resolution order.
2144+
1) The ``type.__new__`` method collects all of the attributes in the class
2145+
namespace that define a :meth:`~object.__set_name__` method;
2146+
2) Those ``__set_name__`` methods are called with the class
2147+
being defined and the assigned name of that particular attribute;
2148+
3) The :meth:`~object.__init_subclass__` hook is called on the
2149+
immediate parent of the new class in its method resolution order.
21452150

21462151
After the class object is created, it is passed to the class decorators
21472152
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
@@ -8458,7 +8458,8 @@ update_all_slots(PyTypeObject* type)
84588458
}
84598459

84608460

8461-
/* Call __set_name__ on all descriptors in a newly generated type */
8461+
/* Call __set_name__ on all attributes (including descriptors)
8462+
in a newly generated type */
84628463
static int
84638464
type_new_set_names(PyTypeObject *type)
84648465
{

0 commit comments

Comments
 (0)