8000 improve documentation with special cases · python/cpython@db0c0c9 · GitHub
[go: up one dir, main page]

Skip to content

Commit db0c0c9

Browse files
committed
improve documentation with special cases
1 parent d8ea90a commit db0c0c9

File tree

1 file changed

+84
-31
lines changed

1 file changed

+84
-31
lines changed

Doc/reference/expressions.rst

Lines changed: 84 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,17 @@ exception.
8383
pair: name; mangling
8484
pair: private; names
8585

86-
.. rubric:: Private name mangling
86+
Private name mangling
87+
^^^^^^^^^^^^^^^^^^^^^
8788

8889
When an identifier that textually occurs in a class definition begins with two
8990
or more underscore characters and does not end in two or more underscores, it
9091
is considered a :dfn:`private name` of that class.
9192

93+
.. seealso::
94+
95+
The :ref:`tutorial on classes <_tut-classdefinition>` for more details.
96+
9297
More precisely, private names are transformed to a longer form before code is
9398
generated for them. If the transformed name is longer than 255 characters,
9499
implementation-defined truncation may happen.
@@ -105,37 +110,9 @@ identifier is used and the transformation rule is defined as follows:
105110
the identifier, e.g., the identifier ``__spam`` occurring in a class
106111
named ``Foo``, ``_Foo`` or ``__Foo`` is transformed to ``_Foo__spam``.
107112

108-
For identifiers declared using :keyword:`import` statements, this rule is
109-
slightly different. Indeed, importing a module with a private name directly
110-
in a class body raises a :exc:`ModuleN 8000 otFoundError` (unless the class name
111-
only consists of underscores), as illustrated by the following example:
112-
113-
.. code-block:: python
114-
115-
class Foo:
116-
import __spam # raises ModuleNotFoundError at runtime
117-
118-
This restriction can be lifted by using the :func:`__import__` function,
119-
in which case the transformation rule is applied normally:
120-
121-
.. code-block:: python
122-
123-
class Foo:
124-
__spam = __import__("__spam")
125-
126-
Foo._Foo__spam.do()
127-
128-
.. note::
113+
.. _private-name-mangling-access:
129114

130-
This restriction does not apply to modules imported as submodules of
131-
private packages, e.g.:
132-
133-
.. code-block:: python
134-
135-
class Foo:
136-
import __spam.util
137-
138-
Foo._Foo__spam.util.do()
115+
.. rubric:: Accessing members with mangled names
139116

140117
The corresponding private member is accessed by its defining class using
141118
its non-transformed name. On the other hand, the transformed name must be
@@ -156,6 +133,82 @@ a subclass):
156133
157134
four = 4 * A()._A__one()
158135
136+
.. _private-name-mangling-imports:
137+
138+
.. rubric:: Mangled names in imports
139+
140+
For identifiers declared using :keyword:`import` statements, the mangling
141+
rule is slightly different. Throughout this paragraph, assume that we have
142+
the following filesystem layout and, unless stated otherwise, the code snippets
143+
are in the ``__main__.py`` file.
144+
145+
.. code-block::
146+
147+
.
148+
├── __main__.py
149+
├── __pkg
150+
│ ├── __init__.py
151+
│ └── mod.py
152+
├── __bar.py
153+
├── __foo.py
154+
└── _Bar__bar.py
155+
156+
Importing a module with a private name directly in a class body may raise
157+
a :exc:`ModuleNotFoundError`, as illustrated by the following example:
158+
159+
.. code-block:: python
160+
161+
class Bar:
162+
# equivalent to import _Bar__bar
163+
import __bar
164+
print(Bar._Bar__bar) # <module '_Bar__bar' from '/_Bar__bar.py'>
165+
166+
class Foo 8000 :
167+
# raises a ModuleNotFoundError at runtime since the interpreter
168+
# tries to import '_Foo__foo' instead of '__foo'
169+
import __foo
170+
171+
If the ``__foo`` module is needed inside the `Foo` class, the import can
172+
be performed via the :func:`__import__` function, in which case the usual
173+
transformation rule is applied (a similar logic applies to :func:`getattr`,
174+
:func:`setattr` and :func:`delattr`, see ):
175+
176+
.. code-block:: python
177+
178+
class Bar:
179+
# explicitly import '__bar' instead of '_Bar__bar'
180+
__bar = __import__("__bar")
181+
print(Bar._Bar__bar) # <module '__bar' from '/__bar.py'>
182+
183+
class Foo:
184+
# explicitly import '__foo' instead of '_Foo__foo'
185+
__foo = __import__("__foo")
186+
print(Foo._Foo__foo) # <module '__foo' from '/__foo.py'>
187+
188+
This restriction does not apply to modules imported as submodules of packages
189+
with private names, e.g.:
190+
191+
.. code-block:: python
192+
193+
class Foo:
194+
import __pkg.mod
195+
196+
print(Foo._Foo__pkg) # <module '__pkg' from '/__pkg/__init__.py'>
197+
print(Foo._Foo__pkg.mod) # <module '__pkg.mod' from '/__pkg/mod.py'>
198+
199+
Note that a class whose name only consists of underscores does not
200+
suffer from those restrictions on :keyword:`import` statements:
201+
202+
.. code-block:: python
203+
204+
class _:
205+
import __bar # imports '__bar'
206+
import __foo # imports '__foo'
207+
import __pkg # imports '__foo'
208+
209+
print(_.__bar) # <module '__bar' from '/__bar.py'>
210+
print(_.__foo) # <module '__foo' from '/__foo.py'>
211+
print(_.__pkg) # <module '__pkg' from '/__pkg/__init__.py'>
159212
160213
.. _atom-literals:
161214

0 commit comments

Comments
 (0)
0