From ebc7f981056be2306f7eeab8075135d2c6df9cce Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 28 Oct 2026 17:30:33 +0100 Subject: [PATCH 1/3] Reword Attribute references MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Blaise Pabon Co-authored-by: Bartosz Sławecki --- Doc/glossary.rst | 7 ++++ Doc/reference/expressions.rst | 76 ++++++++++++++++++++++++----------- 2 files changed, 60 insertions(+), 23 deletions(-) diff --git a/Doc/glossary.rst b/Doc/glossary.rst index a31bd53f06294d..62570d53dfb45c 100644 --- a/Doc/glossary.rst +++ b/Doc/glossary.rst @@ -819,6 +819,13 @@ Glossary See also :term:`subscript`. + instance dictionary + A :term:`dictionary` that stores an object's :term:`attributes `. + Exposed as :attr:`~object.__dict__`. + Note that some attributes may be stored elsewhere, such as in + :attr:`~object.__slots__`, on the object's type, or through + :term:`descriptors `. + interactive Python has an interactive interpreter which means you can enter statements and expressions at the interpreter prompt, immediately diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 2e0b6621eb11c8..436fe391acde84 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1285,13 +1285,25 @@ Primaries .. index:: single: primary -Primaries represent the most tightly bound operations of the language. Their -syntax is: +Primaries represent the most tightly bound operations of the language. +They are: + +- Bare :ref:`atoms ` +- :ref:`Attribute references `, such as ``math.pi`` +- :ref:`Subscriptions and slicings `, such as ``names[0]`` +- :ref:`Calls `, such as ``print()`` + +The formal syntax of primaries is: + +.. grammar-snippet:: + :group: python-grammar -.. productionlist:: python-grammar primary: `atom` | `attributeref` | `subscription` | `call` +.. index:: + pair: exception; AttributeError + .. _attribute-references: Attribute references @@ -1301,30 +1313,48 @@ Attribute references pair: attribute; reference single: . (dot); attribute reference -An attribute reference is a primary followed by a period and a name: - -.. productionlist:: python-grammar - attributeref: `primary` "." `identifier` +An :dfn:`attribute reference` asks an object for an :term:`attribute` -- +a named value associated with that object. +Syntactically, an attribute reference is a :ref:`primary ` +expression followed by a dot (``.``) and an :ref:`identifier ` +that names the attribute. +For example:: -.. index:: - pair: exception; AttributeError - pair: object; module - pair: object; list + >>> import math -The primary must evaluate to an object of a type that supports attribute -references, which most objects do. This object is then asked to produce the -attribute whose name is the identifier. The type and value produced is -determined by the object. Multiple evaluations of the same attribute -reference may yield different objects. + >>> # get the `pi` attribute of the `math` module + >>> math.pi + 3.141592653589793 + + >>> # get the `real` part of a complex number + >>> (3 + 2j).real + 3.0 + +At runtime, the primary expression is evaluated, and the result's +:meth:`~object.__getattribute__` method is called to to produce +the attribute of the given name. +By default, the :meth:`~object.__getattribute__` method looks attributes up +in several places, such as the object's :term:`instance dictionary`, +its type's attributes and descriptors, and the type's +:meth:`~object.__getattr__` method, if any. +Typically, this method returns the same object each time it's called +with a given object and name, or it raises :exc:`AttributeError` if +the attribute is not found. +However, the method is called each time an attribute access is evaluated, +and it can return a differerent object each time. + +To customize the behavior of attribute references on a class you define, +it is typically easier to add a descriptor (for example, using :class:`property`) +or to override :meth:`~object.__getattr__`, rather than override +:meth:`~object.__getattribute__` itself. +See :ref:`attribute-access` for details. + +The formal grammar of attribute references is: -This production can be customized by overriding the -:meth:`~object.__getattribute__` method or the :meth:`~object.__getattr__` -method. The :meth:`!__getattribute__` method is called first and either -returns a value or raises :exc:`AttributeError` if the attribute is not -available. +.. grammar-snippet:: + :group: python-grammar -If an :exc:`AttributeError` is raised and the object has a :meth:`!__getattr__` -method, that method is called as a fallback. + attributeref: `primary` "." `identifier` .. _subscriptions: From a684f03f70bc0284ff58be63435a7e6e1b1d9c97 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 28 Oct 2026 18:01:06 +0100 Subject: [PATCH 2/3] Mention use as assignment targets --- Doc/reference/expressions.rst | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 436fe391acde84..eb04d243ff5756 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1331,9 +1331,9 @@ For example:: 3.0 At runtime, the primary expression is evaluated, and the result's -:meth:`~object.__getattribute__` method is called to to produce +:meth:`~object.__getattribute__` :term:`special method` is called to to produce the attribute of the given name. -By default, the :meth:`~object.__getattribute__` method looks attributes up +By default, :meth:`!__getattribute__` looks attributes up in several places, such as the object's :term:`instance dictionary`, its type's attributes and descriptors, and the type's :meth:`~object.__getattr__` method, if any. @@ -1346,9 +1346,32 @@ and it can return a differerent object each time. To customize the behavior of attribute references on a class you define, it is typically easier to add a descriptor (for example, using :class:`property`) or to override :meth:`~object.__getattr__`, rather than override -:meth:`~object.__getattribute__` itself. +:meth:`!__getattribute__` itself. See :ref:`attribute-access` for details. +Attribute references may also be used as targets in +:ref:`assignment ` or :ref:`deletion ` statements. +In these cases, the interpreter will call an object's +:meth:`~object.__setattr__` or :meth:`~object.__delattr__` +:term:`special method`, respectively, +instead of :meth:`~object.__getattribute__`. + +.. code-block:: + + >>> from types import SimpleNamespace + >>> obj = SimpleNamespace() + + >>> obj.color = 'green' # set the `color` attribute on `obj` + >>> obj.color + 'green' + >>> obj + namespace(color='green') + + >>> del obj.color # delete the `color` attribute on `obj` + >>> obj + namespace() + + The formal grammar of attribute references is: .. grammar-snippet:: From 4b61df5de9fcade79a565fec29ea4177f500bcd4 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 4 Nov 2026 16:56:43 +0100 Subject: [PATCH 3/3] More rewording Co-authored-by: Blaise Pabon --- Doc/reference/expressions.rst | 39 ++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 5e4a2da8313f23..5639594e459c50 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1288,10 +1288,10 @@ Primaries Primaries represent the most tightly bound operations of the language. They are: -- Bare :ref:`atoms ` -- :ref:`Attribute references `, such as ``math.pi`` -- :ref:`Subscriptions and slicings `, such as ``names[0]`` -- :ref:`Calls `, such as ``print()`` +- bare :ref:`atoms `, +- :ref:`attribute references `, such as ``math.pi``, +- :ref:`subscriptions and slicings `, such as ``names[0]``, and +- :ref:`calls `, such as ``print()``. The formal syntax of primaries is: @@ -1322,12 +1322,10 @@ For example:: >>> import math - >>> # get the `pi` attribute of the `math` module - >>> math.pi + >>> math.pi # get the `pi` attribute of the `math` module 3.141592653589793 - >>> # get the `real` part of a complex number - >>> (3 + 2j).real + >>> (3 + 2j).real # get the `real` part of a complex number 3.0 At runtime, the primary expression is evaluated, and the result's @@ -1337,17 +1335,19 @@ By default, :meth:`!__getattribute__` looks attributes up in several places, such as the object's :term:`instance dictionary`, its type's attributes and descriptors, and the type's :meth:`~object.__getattr__` method, if any. -Typically, this method returns the same object each time it's called -with a given object and name, or it raises :exc:`AttributeError` if -the attribute is not found. +Typically, :meth:`!__getattribute__` raises :exc:`AttributeError` if +the attribute is not found, and it returns the same object each time +it's called with a given object and name. However, the method is called each time an attribute access is evaluated, -and it can return a differerent object each time. +and it can raise different errors or return a differerent object each time. -To customize the behavior of attribute references on a class you define, -it is typically easier to add a descriptor (for example, using :class:`property`) -or to override :meth:`~object.__getattr__`, rather than override -:meth:`!__getattribute__` itself. -See :ref:`attribute-access` for details. +.. note:: + + When customizing the behavior of attribute references on a class you define, + consider adding a descriptor (for example, using :class:`property`) + or overriding :meth:`~object.__getattr__`, rather than replacing the entire + attribute lookup mechanism by overriding :meth:`!__getattribute__` itself. + See :ref:`attribute-access` for details. Attribute references may also be used as targets in :ref:`assignment ` or :ref:`deletion ` statements. @@ -1371,6 +1371,11 @@ instead of :meth:`~object.__getattribute__`. >>> obj namespace() + >>> del obj.color # delete an attribute that doesn't exist any more + Traceback (most recent call last): + ... + AttributeError: 'types.SimpleNamespace' object has no attribute 'color' + The formal grammar of attribute references is: