mirror of https://github.com/python/cpython
Improve discussion about how __getattr__ is invoked. (GH-31435)
This commit is contained in:
parent
0a8a8e7454
commit
12a2e41e8a
|
@ -696,10 +696,14 @@ a pure Python equivalent:
|
|||
>>> b.g == b['g'] == ('getattr_hook', b, 'g')
|
||||
True
|
||||
|
||||
Note, there is no :meth:`__getattr__` hook in the :meth:`__getattribute__`
|
||||
code. That is why calling :meth:`__getattribute__` directly or with
|
||||
``super().__getattribute__`` will bypass :meth:`__getattr__` entirely.
|
||||
|
||||
Interestingly, attribute lookup doesn't call :meth:`object.__getattribute__`
|
||||
directly. Instead, both the dot operator and the :func:`getattr` function
|
||||
perform attribute lookup by way of a helper function:
|
||||
Instead, it is the dot operator and the :func:`getattr` function that are
|
||||
responsible for invoking :meth:`__getattr__` whenever :meth:`__getattribute__`
|
||||
raises an :exc:`AttributeError`. Their logic is encapsulated in a helper
|
||||
function:
|
||||
|
||||
.. testcode::
|
||||
|
||||
|
@ -744,12 +748,6 @@ perform attribute lookup by way of a helper function:
|
|||
...
|
||||
AttributeError: 'ClassWithoutGetAttr' object has no attribute 'z'
|
||||
|
||||
So if :meth:`__getattr__` exists, it is called whenever :meth:`__getattribute__`
|
||||
raises :exc:`AttributeError` (either directly or in one of the descriptor calls).
|
||||
|
||||
Also, if a user calls :meth:`object.__getattribute__` directly, the
|
||||
:meth:`__getattr__` hook is bypassed entirely.
|
||||
|
||||
|
||||
Invocation from a class
|
||||
-----------------------
|
||||
|
|
Loading…
Reference in New Issue