Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-101100: Improve documentation for attributes on instance methods #112832

Merged
merged 1 commit into from
Dec 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Doc/library/inspect.rst
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ attributes (see :ref:`import-mod-attrs` for module attributes):
Methods implemented via descriptors that also pass one of the other tests
return ``False`` from the :func:`ismethoddescriptor` test, simply because the
other tests promise more -- you can, e.g., count on having the
:ref:`__func__ <instance-methods>` attribute (etc) when an object passes
:attr:`~method.__func__` attribute (etc) when an object passes
:func:`ismethod`.


Expand Down
23 changes: 14 additions & 9 deletions Doc/library/stdtypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5327,26 +5327,31 @@

.. index:: pair: object; method

Methods are functions that are called using the attribute notation. There are

Check warning on line 5330 in Doc/library/stdtypes.rst

View workflow job for this annotation

GitHub Actions / Docs / Docs

py:meth reference target not found: append
two flavors: built-in methods (such as :meth:`append` on lists) and class
instance methods. Built-in methods are described with the types that support
them.
two flavors: :ref:`built-in methods <builtin-methods>` (such as :meth:`append`
on lists) and :ref:`class instance method <instance-methods>`.
Built-in methods are described with the types that support them.

If you access a method (a function defined in a class namespace) through an
instance, you get a special object: a :dfn:`bound method` (also called
:dfn:`instance method`) object. When called, it will add the ``self`` argument
:ref:`instance method <instance-methods>`) object. When called, it will add
the ``self`` argument
to the argument list. Bound methods have two special read-only attributes:
``m.__self__`` is the object on which the method operates, and ``m.__func__`` is
:attr:`m.__self__ <method.__self__>` is the object on which the method
operates, and :attr:`m.__func__ <method.__func__>` is
the function implementing the method. Calling ``m(arg-1, arg-2, ..., arg-n)``
is completely equivalent to calling ``m.__func__(m.__self__, arg-1, arg-2, ...,
arg-n)``.

Like function objects, bound method objects support getting arbitrary
Like :ref:`function objects <user-defined-funcs>`, bound method objects support
getting arbitrary
attributes. However, since method attributes are actually stored on the
underlying function object (``meth.__func__``), setting method attributes on
underlying function object (:attr:`method.__func__`), setting method attributes on
bound methods is disallowed. Attempting to set an attribute on a method
results in an :exc:`AttributeError` being raised. In order to set a method
attribute, you need to explicitly set it on the underlying function object::
attribute, you need to explicitly set it on the underlying function object:

.. doctest::

>>> class C:
... def method(self):
Expand All @@ -5361,7 +5366,7 @@
>>> c.method.whoami
'my name is method'

See :ref:`types` for more information.
See :ref:`instance-methods` for more information.


.. index:: object; code, code object
Expand Down
77 changes: 52 additions & 25 deletions Doc/reference/datamodel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,8 @@ These are the types to which the function call operation (see section
:ref:`calls`) can be applied:


.. _user-defined-funcs:

User-defined functions
^^^^^^^^^^^^^^^^^^^^^^

Expand Down Expand Up @@ -654,43 +656,64 @@ callable object (normally a user-defined function).
single: __name__ (method attribute)
single: __module__ (method attribute)

Special read-only attributes: :attr:`__self__` is the class instance object,
:attr:`__func__` is the function object; :attr:`__doc__` is the method's
documentation (same as ``__func__.__doc__``); :attr:`~definition.__name__` is the
method name (same as ``__func__.__name__``); :attr:`__module__` is the
name of the module the method was defined in, or ``None`` if unavailable.
Special read-only attributes:

.. list-table::

* - .. attribute:: method.__self__
- Refers to the class instance object to which the method is
:ref:`bound <method-binding>`

* - .. attribute:: method.__func__
- Refers to the original function object

* - .. attribute:: method.__doc__
- The method's documentation (same as :attr:`!method.__func__.__doc__`).
A :class:`string <str>` if the original function had a docstring, else
``None``.

* - .. attribute:: method.__name__
- The name of the method (same as :attr:`!method.__func__.__name__`)

* - .. attribute:: method.__module__
- The name of the module the method was defined in, or ``None`` if
unavailable.

Methods also support accessing (but not setting) the arbitrary function
attributes on the underlying function object.
attributes on the underlying :ref:`function object <user-defined-funcs>`.

User-defined method objects may be created when getting an attribute of a
class (perhaps via an instance of that class), if that attribute is a
user-defined function object or a class method object.
user-defined :ref:`function object <user-defined-funcs>` or a
:class:`classmethod` object.

.. _method-binding:

When an instance method object is created by retrieving a user-defined
function object from a class via one of its instances, its
:attr:`__self__` attribute is the instance, and the method object is said
to be bound. The new method's :attr:`__func__` attribute is the original
function object.

When an instance method object is created by retrieving a class method
object from a class or instance, its :attr:`__self__` attribute is the
class itself, and its :attr:`__func__` attribute is the function object
:ref:`function object <user-defined-funcs>` from a class via one of its
instances, its :attr:`~method.__self__` attribute is the instance, and the
method object is said to be *bound*. The new method's :attr:`~method.__func__`
attribute is the original function object.

When an instance method object is created by retrieving a :class:`classmethod`
object from a class or instance, its :attr:`~method.__self__` attribute is the
class itself, and its :attr:`~method.__func__` attribute is the function object
underlying the class method.

When an instance method object is called, the underlying function
(:attr:`__func__`) is called, inserting the class instance
(:attr:`__self__`) in front of the argument list. For instance, when
(:attr:`~method.__func__`) is called, inserting the class instance
(:attr:`~method.__self__`) in front of the argument list. For instance, when
:class:`!C` is a class which contains a definition for a function
:meth:`!f`, and ``x`` is an instance of :class:`!C`, calling ``x.f(1)`` is
equivalent to calling ``C.f(x, 1)``.

When an instance method object is derived from a class method object, the
"class instance" stored in :attr:`__self__` will actually be the class
When an instance method object is derived from a :class:`classmethod` object, the
"class instance" stored in :attr:`~method.__self__` will actually be the class
itself, so that calling either ``x.f(1)`` or ``C.f(1)`` is equivalent to
calling ``f(C,1)`` where ``f`` is the underlying function.

Note that the transformation from function object to instance method
Note that the transformation from :ref:`function object <user-defined-funcs>`
to instance method
object happens each time the attribute is retrieved from the instance. In
some cases, a fruitful optimization is to assign the attribute to a local
variable and call that local variable. Also notice that this
Expand Down Expand Up @@ -774,6 +797,8 @@ set to ``None`` (but see the next item); :attr:`__module__` is the name of
the module the function was defined in or ``None`` if unavailable.


.. _builtin-methods:

Built-in methods
^^^^^^^^^^^^^^^^

Expand All @@ -785,8 +810,9 @@ Built-in methods
This is really a different disguise of a built-in function, this time containing
an object passed to the C function as an implicit extra argument. An example of
a built-in method is ``alist.append()``, assuming *alist* is a list object. In
this case, the special read-only attribute :attr:`__self__` is set to the object
denoted by *alist*.
this case, the special read-only attribute :attr:`!__self__` is set to the object
denoted by *alist*. (The attribute has the same semantics as it does with
:attr:`other instance methods <method.__self__>`.)


Classes
Expand Down Expand Up @@ -901,8 +927,9 @@ https://www.python.org/download/releases/2.3/mro/.

When a class attribute reference (for class :class:`!C`, say) would yield a
class method object, it is transformed into an instance method object whose
:attr:`__self__` attribute is :class:`!C`. When it would yield a static
method object, it is transformed into the object wrapped by the static method
:attr:`~method.__self__` attribute is :class:`!C`.
When it would yield a :class:`staticmethod` object,
it is transformed into the object wrapped by the static method
object. See section :ref:`descriptors` for another way in which attributes
retrieved from a class may differ from those actually contained in its
:attr:`~object.__dict__`.
Expand Down Expand Up @@ -970,7 +997,7 @@ in which attribute references are searched. When an attribute is not found
there, and the instance's class has an attribute by that name, the search
continues with the class attributes. If a class attribute is found that is a
user-defined function object, it is transformed into an instance method
object whose :attr:`__self__` attribute is the instance. Static method and
object whose :attr:`~method.__self__` attribute is the instance. Static method and
class method objects are also transformed; see above under "Classes". See
section :ref:`descriptors` for another way in which attributes of a class
retrieved via its instances may differ from the objects actually stored in
Expand Down
6 changes: 4 additions & 2 deletions Doc/tutorial/classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -769,8 +769,10 @@ data from a string buffer instead, and pass it as an argument.
or arithmetic operators, and assigning such a "pseudo-file" to sys.stdin will
not cause the interpreter to read further input from it.)

Instance method objects have attributes, too: ``m.__self__`` is the instance
object with the method :meth:`!m`, and ``m.__func__`` is the function object
:ref:`Instance method objects <instance-methods>` have attributes, too:
:attr:`m.__self__ <method.__self__>` is the instance
object with the method :meth:`!m`, and :attr:`m.__func__ <method.__func__>` is
the :ref:`function object <user-defined-funcs>`
corresponding to the method.


Expand Down
4 changes: 2 additions & 2 deletions Doc/whatsnew/2.6.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1678,8 +1678,8 @@ Some smaller changes made to the core Python language are:

* Instance method objects have new attributes for the object and function
comprising the method; the new synonym for :attr:`!im_self` is
:ref:`__self__ <instance-methods>`, and :attr:`!im_func` is also available as
:ref:`__func__ <instance-methods>`.
:attr:`~method.__self__`, and :attr:`!im_func` is also available as
:attr:`~method.__func__`.
The old names are still supported in Python 2.6, but are gone in 3.0.

* An obscure change: when you use the :func:`locals` function inside a
Expand Down
5 changes: 3 additions & 2 deletions Doc/whatsnew/2.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -858,9 +858,10 @@ Some smaller changes made to the core Python language are:

.. XXX bytearray doesn't seem to be documented

* When using ``@classmethod`` and ``@staticmethod`` to wrap
* When using :class:`@classmethod <classmethod>` and
:class:`@staticmethod <staticmethod>` to wrap
methods as class or static methods, the wrapper object now
exposes the wrapped function as their :ref:`__func__ <instance-methods>`
exposes the wrapped function as their :attr:`~method.__func__`
attribute.
(Contributed by Amaury Forgeot d'Arc, after a suggestion by
George Sakkis; :issue:`5982`.)
Expand Down