Skip to content

Commit

Permalink
[3.11] Improve references in the tutorial (pythonGH-108069) (pythonGH…
Browse files Browse the repository at this point in the history
…-108204)

* Use full qualified names for references (even if they do not work now,
  they will work in future).
* Silence references to examples.
(cherry picked from commit 622ddc4)
  • Loading branch information
serhiy-storchaka committed Aug 21, 2023
1 parent a372274 commit be99653
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 49 deletions.
2 changes: 0 additions & 2 deletions Doc/tools/.nitignore
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,7 @@ Doc/tutorial/appendix.rst
Doc/tutorial/classes.rst
Doc/tutorial/controlflow.rst
Doc/tutorial/datastructures.rst
Doc/tutorial/inputoutput.rst
Doc/tutorial/introduction.rst
Doc/tutorial/modules.rst
Doc/using/cmdline.rst
Doc/using/configure.rst
Doc/using/windows.rst
Expand Down
43 changes: 22 additions & 21 deletions Doc/tutorial/classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Attributes may be read-only or writable. In the latter case, assignment to
attributes is possible. Module attributes are writable: you can write
``modname.the_answer = 42``. Writable attributes may also be deleted with the
:keyword:`del` statement. For example, ``del modname.the_answer`` will remove
the attribute :attr:`the_answer` from the object named by ``modname``.
the attribute :attr:`!the_answer` from the object named by ``modname``.

Namespaces are created at different moments and have different lifetimes. The
namespace containing the built-in names is created when the Python interpreter
Expand Down Expand Up @@ -249,7 +249,7 @@ created. This is basically a wrapper around the contents of the namespace
created by the class definition; we'll learn more about class objects in the
next section. The original local scope (the one in effect just before the class
definition was entered) is reinstated, and the class object is bound here to the
class name given in the class definition header (:class:`ClassName` in the
class name given in the class definition header (:class:`!ClassName` in the
example).


Expand Down Expand Up @@ -291,20 +291,20 @@ variable ``x``.
The instantiation operation ("calling" a class object) creates an empty object.
Many classes like to create objects with instances customized to a specific
initial state. Therefore a class may define a special method named
:meth:`__init__`, like this::
:meth:`~object.__init__`, like this::

def __init__(self):
self.data = []

When a class defines an :meth:`__init__` method, class instantiation
automatically invokes :meth:`__init__` for the newly created class instance. So
When a class defines an :meth:`~object.__init__` method, class instantiation
automatically invokes :meth:`!__init__` for the newly created class instance. So
in this example, a new, initialized instance can be obtained by::

x = MyClass()

Of course, the :meth:`__init__` method may have arguments for greater
Of course, the :meth:`~object.__init__` method may have arguments for greater
flexibility. In that case, arguments given to the class instantiation operator
are passed on to :meth:`__init__`. For example, ::
are passed on to :meth:`!__init__`. For example, ::

>>> class Complex:
... def __init__(self, realpart, imagpart):
Expand All @@ -328,7 +328,7 @@ attribute names: data attributes and methods.
*data attributes* correspond to "instance variables" in Smalltalk, and to "data
members" in C++. Data attributes need not be declared; like local variables,
they spring into existence when they are first assigned to. For example, if
``x`` is the instance of :class:`MyClass` created above, the following piece of
``x`` is the instance of :class:`!MyClass` created above, the following piece of
code will print the value ``16``, without leaving a trace::

x.counter = 1
Expand Down Expand Up @@ -363,7 +363,7 @@ Usually, a method is called right after it is bound::

x.f()

In the :class:`MyClass` example, this will return the string ``'hello world'``.
In the :class:`!MyClass` example, this will return the string ``'hello world'``.
However, it is not necessary to call a method right away: ``x.f`` is a method
object, and can be stored away and called at a later time. For example::

Expand All @@ -375,7 +375,7 @@ will continue to print ``hello world`` until the end of time.

What exactly happens when a method is called? You may have noticed that
``x.f()`` was called without an argument above, even though the function
definition for :meth:`f` specified an argument. What happened to the argument?
definition for :meth:`!f` specified an argument. What happened to the argument?
Surely Python raises an exception when a function that requires an argument is
called without any --- even if the argument isn't actually used...

Expand Down Expand Up @@ -532,9 +532,9 @@ variable in the class is also ok. For example::

h = g

Now ``f``, ``g`` and ``h`` are all attributes of class :class:`C` that refer to
Now ``f``, ``g`` and ``h`` are all attributes of class :class:`!C` that refer to
function objects, and consequently they are all methods of instances of
:class:`C` --- ``h`` being exactly equivalent to ``g``. Note that this practice
:class:`!C` --- ``h`` being exactly equivalent to ``g``. Note that this practice
usually only serves to confuse the reader of a program.

Methods may call other methods by using method attributes of the ``self``
Expand Down Expand Up @@ -581,7 +581,7 @@ this::
.
<statement-N>

The name :class:`BaseClassName` must be defined in a scope containing the
The name :class:`!BaseClassName` must be defined in a scope containing the
derived class definition. In place of a base class name, other arbitrary
expressions are also allowed. This can be useful, for example, when the base
class is defined in another module::
Expand Down Expand Up @@ -644,9 +644,9 @@ multiple base classes looks like this::
For most purposes, in the simplest cases, you can think of the search for
attributes inherited from a parent class as depth-first, left-to-right, not
searching twice in the same class where there is an overlap in the hierarchy.
Thus, if an attribute is not found in :class:`DerivedClassName`, it is searched
for in :class:`Base1`, then (recursively) in the base classes of :class:`Base1`,
and if it was not found there, it was searched for in :class:`Base2`, and so on.
Thus, if an attribute is not found in :class:`!DerivedClassName`, it is searched
for in :class:`!Base1`, then (recursively) in the base classes of :class:`!Base1`,
and if it was not found there, it was searched for in :class:`!Base2`, and so on.

In fact, it is slightly more complex than that; the method resolution order
changes dynamically to support cooperative calls to :func:`super`. This
Expand Down Expand Up @@ -759,7 +759,8 @@ is to use :mod:`dataclasses` for this purpose::
A piece of Python code that expects a particular abstract data type can often be
passed a class that emulates the methods of that data type instead. For
instance, if you have a function that formats some data from a file object, you
can define a class with methods :meth:`read` and :meth:`!readline` that get the
can define a class with methods :meth:`~io.TextIOBase.read` and
:meth:`~io.TextIOBase.readline` that get the
data from a string buffer instead, and pass it as an argument.

.. (Unfortunately, this technique has its limitations: a class can't define
Expand All @@ -768,7 +769,7 @@ data from a string buffer instead, and pass it as an argument.
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
object with the method :meth:`!m`, and ``m.__func__`` is the function object
corresponding to the method.


Expand Down Expand Up @@ -817,9 +818,9 @@ using the :func:`next` built-in function; this example shows how it all works::
StopIteration

Having seen the mechanics behind the iterator protocol, it is easy to add
iterator behavior to your classes. Define an :meth:`__iter__` method which
iterator behavior to your classes. Define an :meth:`~container.__iter__` method which
returns an object with a :meth:`~iterator.__next__` method. If the class
defines :meth:`__next__`, then :meth:`__iter__` can just return ``self``::
defines :meth:`!__next__`, then :meth:`!__iter__` can just return ``self``::

class Reverse:
"""Iterator for looping over a sequence backwards."""
Expand Down Expand Up @@ -878,7 +879,7 @@ easy to create::

Anything that can be done with generators can also be done with class-based
iterators as described in the previous section. What makes generators so
compact is that the :meth:`__iter__` and :meth:`~generator.__next__` methods
compact is that the :meth:`~iterator.__iter__` and :meth:`~generator.__next__` methods
are created automatically.

Another key feature is that the local variables and execution state are
Expand Down
2 changes: 1 addition & 1 deletion Doc/tutorial/controlflow.rst
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ This example, as usual, demonstrates some new Python features:
Different types define different methods. Methods of different types may have
the same name without causing ambiguity. (It is possible to define your own
object types and methods, using *classes*, see :ref:`tut-classes`)
The method :meth:`append` shown in the example is defined for list objects; it
The method :meth:`~list.append` shown in the example is defined for list objects; it
adds a new element at the end of the list. In this example it is equivalent to
``result = result + [a]``, but more efficient.

Expand Down
12 changes: 6 additions & 6 deletions Doc/tutorial/datastructures.rst
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ Using Lists as Stacks

The list methods make it very easy to use a list as a stack, where the last
element added is the first element retrieved ("last-in, first-out"). To add an
item to the top of the stack, use :meth:`append`. To retrieve an item from the
top of the stack, use :meth:`pop` without an explicit index. For example::
item to the top of the stack, use :meth:`~list.append`. To retrieve an item from the
top of the stack, use :meth:`~list.pop` without an explicit index. For example::

>>> stack = [3, 4, 5]
>>> stack.append(6)
Expand Down Expand Up @@ -341,7 +341,7 @@ The :keyword:`!del` statement
=============================

There is a way to remove an item from a list given its index instead of its
value: the :keyword:`del` statement. This differs from the :meth:`pop` method
value: the :keyword:`del` statement. This differs from the :meth:`~list.pop` method
which returns a value. The :keyword:`!del` statement can also be used to remove
slices from a list or clear the entire list (which we did earlier by assignment
of an empty list to the slice). For example::
Expand Down Expand Up @@ -501,8 +501,8 @@ any immutable type; strings and numbers can always be keys. Tuples can be used
as keys if they contain only strings, numbers, or tuples; if a tuple contains
any mutable object either directly or indirectly, it cannot be used as a key.
You can't use lists as keys, since lists can be modified in place using index
assignments, slice assignments, or methods like :meth:`append` and
:meth:`extend`.
assignments, slice assignments, or methods like :meth:`~list.append` and
:meth:`~list.extend`.

It is best to think of a dictionary as a set of *key: value* pairs,
with the requirement that the keys are unique (within one dictionary). A pair of
Expand Down Expand Up @@ -567,7 +567,7 @@ Looping Techniques
==================

When looping through dictionaries, the key and corresponding value can be
retrieved at the same time using the :meth:`items` method. ::
retrieved at the same time using the :meth:`~dict.items` method. ::

>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.items():
Expand Down
8 changes: 4 additions & 4 deletions Doc/tutorial/inputoutput.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Fancier Output Formatting
=========================

So far we've encountered two ways of writing values: *expression statements* and
the :func:`print` function. (A third way is using the :meth:`write` method
the :func:`print` function. (A third way is using the :meth:`~io.TextIOBase.write` method
of file objects; the standard output file can be referenced as ``sys.stdout``.
See the Library Reference for more information on this.)

Expand Down Expand Up @@ -456,8 +456,8 @@ to the very file end with ``seek(0, 2)``) and the only valid *offset* values are
those returned from the ``f.tell()``, or zero. Any other *offset* value produces
undefined behaviour.

File objects have some additional methods, such as :meth:`~file.isatty` and
:meth:`~file.truncate` which are less frequently used; consult the Library
File objects have some additional methods, such as :meth:`~io.IOBase.isatty` and
:meth:`~io.IOBase.truncate` which are less frequently used; consult the Library
Reference for a complete guide to file objects.


Expand All @@ -469,7 +469,7 @@ Saving structured data with :mod:`json`
.. index:: pair: module; json

Strings can easily be written to and read from a file. Numbers take a bit more
effort, since the :meth:`read` method only returns strings, which will have to
effort, since the :meth:`~io.TextIOBase.read` method only returns strings, which will have to
be passed to a function like :func:`int`, which takes a string like ``'123'``
and returns its numeric value 123. When you want to save more complex data
types like nested lists and dictionaries, parsing and serializing by hand
Expand Down
30 changes: 15 additions & 15 deletions Doc/tutorial/modules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ The Module Search Path

.. index:: triple: module; search; path

When a module named :mod:`spam` is imported, the interpreter first searches for
When a module named :mod:`!spam` is imported, the interpreter first searches for
a built-in module with that name. These module names are listed in
:data:`sys.builtin_module_names`. If not found, it then searches for a file
named :file:`spam.py` in a list of directories given by the variable
Expand Down Expand Up @@ -389,7 +389,7 @@ Packages
========

Packages are a way of structuring Python's module namespace by using "dotted
module names". For example, the module name :mod:`A.B` designates a submodule
module names". For example, the module name :mod:`!A.B` designates a submodule
named ``B`` in a package named ``A``. Just like the use of modules saves the
authors of different modules from having to worry about each other's global
variable names, the use of dotted module names saves the authors of multi-module
Expand Down Expand Up @@ -448,7 +448,7 @@ example::

import sound.effects.echo

This loads the submodule :mod:`sound.effects.echo`. It must be referenced with
This loads the submodule :mod:`!sound.effects.echo`. It must be referenced with
its full name. ::

sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
Expand All @@ -457,7 +457,7 @@ An alternative way of importing the submodule is::

from sound.effects import echo

This also loads the submodule :mod:`echo`, and makes it available without its
This also loads the submodule :mod:`!echo`, and makes it available without its
package prefix, so it can be used as follows::

echo.echofilter(input, output, delay=0.7, atten=4)
Expand All @@ -466,8 +466,8 @@ Yet another variation is to import the desired function or variable directly::

from sound.effects.echo import echofilter

Again, this loads the submodule :mod:`echo`, but this makes its function
:func:`echofilter` directly available::
Again, this loads the submodule :mod:`!echo`, but this makes its function
:func:`!echofilter` directly available::

echofilter(input, output, delay=0.7, atten=4)

Expand Down Expand Up @@ -510,7 +510,7 @@ code::
__all__ = ["echo", "surround", "reverse"]

This would mean that ``from sound.effects import *`` would import the three
named submodules of the :mod:`sound.effects` package.
named submodules of the :mod:`!sound.effects` package.

Be aware that submodules might become shadowed by locally defined names. For
example, if you added a ``reverse`` function to the
Expand All @@ -529,8 +529,8 @@ would only import the two submodules ``echo`` and ``surround``, but *not* the
return msg[::-1] # in the case of a 'from sound.effects import *'

If ``__all__`` is not defined, the statement ``from sound.effects import *``
does *not* import all submodules from the package :mod:`sound.effects` into the
current namespace; it only ensures that the package :mod:`sound.effects` has
does *not* import all submodules from the package :mod:`!sound.effects` into the
current namespace; it only ensures that the package :mod:`!sound.effects` has
been imported (possibly running any initialization code in :file:`__init__.py`)
and then imports whatever names are defined in the package. This includes any
names defined (and submodules explicitly loaded) by :file:`__init__.py`. It
Expand All @@ -541,8 +541,8 @@ previous :keyword:`import` statements. Consider this code::
import sound.effects.surround
from sound.effects import *

In this example, the :mod:`echo` and :mod:`surround` modules are imported in the
current namespace because they are defined in the :mod:`sound.effects` package
In this example, the :mod:`!echo` and :mod:`!surround` modules are imported in the
current namespace because they are defined in the :mod:`!sound.effects` package
when the ``from...import`` statement is executed. (This also works when
``__all__`` is defined.)

Expand All @@ -561,15 +561,15 @@ packages.
Intra-package References
------------------------

When packages are structured into subpackages (as with the :mod:`sound` package
When packages are structured into subpackages (as with the :mod:`!sound` package
in the example), you can use absolute imports to refer to submodules of siblings
packages. For example, if the module :mod:`sound.filters.vocoder` needs to use
the :mod:`echo` module in the :mod:`sound.effects` package, it can use ``from
packages. For example, if the module :mod:`!sound.filters.vocoder` needs to use
the :mod:`!echo` module in the :mod:`!sound.effects` package, it can use ``from
sound.effects import echo``.

You can also write relative imports, with the ``from module import name`` form
of import statement. These imports use leading dots to indicate the current and
parent packages involved in the relative import. From the :mod:`surround`
parent packages involved in the relative import. From the :mod:`!surround`
module for example, you might use::

from . import echo
Expand Down

0 comments on commit be99653

Please sign in to comment.