PEP 257 in Russian. (Docstrings Agreement)

Hello, Habr. There are times when you want to immerse yourself in the language as much as possible and understand all its subtleties. In the case of Python, one of the best ways to do this is to read the documentation and PEPs on the official website. I didn’t do this at the time, because I couldn’t understand many of the “technical” aspects, and there were no variants of the Russian translation. Now I decided to translate PEP-257 myself, which tells about the correct documentation of the code, because for sure this will help beginners better understand the true “Python” approach to writing code. I translated the code examples into Russian, but only in order to better convey the meaning. In real programming, try writing documentation lines in English. I also say right away that as a synonym for the term “docstring” I used the words: “documentation” and “documentation lines”. Well, let's move on to the translation itself.

Pep257
Title:Docstrings Agreement
Authors:David Goodger <goodger at python.org>, Guido van Rossum <guido at python.org>
Discussion:doc-sig at python.org
Status:Active
A type:Informational
Created:May 29, 2001
Publication:13-June-2001

annotation


This PEP documents the semantics and conventions associated with the use of Python docstrings.

Justification


The purpose of this PEP is to standardize the high-level structure of document lines: to describe what exactly they should contain and explain (We will not discuss the actual markup syntax). PEP does not contain strict guidelines, but recommendations:
“Conventional conventions provide clarity, consistency, ease of maintenance and foster good programming habits. But they do not force you to act against your will. This is Python! ”

Tim Peters on comp.lang.python, 2001-06-16

If you avoid generally accepted agreements, you will be squinted at the worst. But there are some applications (for example, documentation systems like Docutils) that will allow you to achieve a better result if you know about the agreements and follow them.

Specification


What is a Docstring?


A documentation string is a string literal that is the first statement in a module, function, class, or method definition. Such a string becomes available when handling the special __doc__ attribute of this object.

All libraries, as well as functions and classes exported by them, must have docstring. Public methods (including the __ init__ constructor) must also have documentation. The package itself can be documented inside the __init__.py file located in its corresponding directory.

String literals found elsewhere in the code can also play the role of documentation. They are not recognized by Python byte-code compiler and are not available as object attributes during program execution (i.e. they lack information in __ doc__). But there are two additional types of documentation lines that are retrieved using other software tools:

  1. String literals that occur immediately after a simple assignment at the module, class or __init__ level are called “attribute documentation strings”. (attribute docstrings)
  2. String literals that occur immediately after another line of documentation are called "additional documentation lines." (additional docstrings)

Please see PEP 258, “Docutils Project Specification,” for more details on attribute and additional docstrings.

[approx. ed. Explanation of PEP 258]
def f(x):
    """  docstring   __doc__ ."""
    """
     "additional docstrings",   , 
        Docutils.
    """
    return x**2

f.a = 1
""" "attribute docstrings"   : f.a"""

For consistency, always use the "" "triple double quotes" "" around the documentation line. If you use backslash characters ("\"), then use the r "" "raw double-quoted string" "" in your documentation. For docstring containing Unicode characters, use u "" "Unicode string in triple double quotes" "". [approx. unicode strings have lost their meaning in python 3.x]

There are two forms of docstring: single-line and multi-line.

Single line documentation lines


Single-line strings are used for obvious cases and they should really be on the same line. For instance:

def kos_root():
    """    root KOS"""
    global _kos_root
    if _kos_root: return _kos_root
    ...

Remarks:

  • . .
  • , . docstring .
  • , .
  • — «», . (« », « »), . , : « ...».

    « » «Return pathname» «Returns pathname». PEP-257 , .
  • «», / ( ). :

    def function(a, b):
        """function(a, b) -> list"""
    

    , C ( ), . . - :

    def function(a, b):
        def function(a, b):
        """ X   ."""
    

    ( -, « X» !)

    , : « », «description» . , , .



Multi-line documentation consists of a summary line that has the same structure as a single-line docstring, followed by an empty line, and then a more complex description. "Summary line" can be used by means of automatic documentation; therefore, it is so important to place it on one line and then make a pass in one line. The summary line is written immediately after the opening quotation marks, but it is allowed to do a hyphenation and start from the next line. [approx. after this sentence, I was happy, because there were people who persistently tried to prove to me that it was impossible to carry out a transfer in any case :-)] At the same time, the entire docstring should have the same indentation as the opening quotation marks of the first line (see example below).

Leave a blank line after all documentation (single-line or multi-line) that are used in the class; generally speaking, class methods should be separated from each other by one empty line, therefore the class documentation line should also be separated in this way from the first method.

The documentation of the script (stand-alone program) is a message “about proper use” and will probably be printed when the script is called with invalid or missing arguments (or with the “-h” option to get “help”). Such a documentation line should describe the functionality and syntax of the script parameters, as well as environment variables and files used. This message may turn out to be rather complicated (the manual is several full screens long), but at the same time it should be convenient for new users so that they can use the command correctly. Also, the manual should give a clear description of all parameters and arguments for more experienced users.

The module documentation should usually contain a list of classes, exceptions and functions (and any other important objects) that are exported using the library, as well as a one-line explanation for each of them. (This summary, as a rule, gives less details than the summary line in the docstring of the object itself). The package documentation (i.e., the module docstring in __init__.py) should also describe and list the modules and subpackages exported by the main one.

The documentation of a function or method should describe their behavior, arguments, return values, side effects, exceptions, and restrictions on when they can be called (if any). You must also specify optional arguments. It should be clarified whether the key arguments are part of the interface.

Class documentation should summarize its behavior and list public methods as well as instance variables. If the class will have subclasses with an additional interface, then this interface must be specified separately (but everything is also in this documentation). The class constructor must have its own separate documentation line for the __init__ method. Independent (individual) methods should have their own documentation.

If a class is a descendant and its behavior is mainly inherited from the main class, it is necessary to mention this in its documentation and describe possible differences. Use the verb “override” to indicate that a method has been changed and that, as a result, the superclass method will not be called. Use the verb “extends” if the subclass method calls the superclass method (in addition to its own behavior).

Do not use the Emacs convention to mention function arguments or methods in uppercase. Python is case-sensitive, and argument names can sometimes be used when passing them by keys, so the documentation must contain real variable names. It is best to list each argument on a separate line. For instance:

def complex(real=0.0, imag=0.0):
    """  .

     :
    real --   (  0.0)
    imag --   (  0.0)
    """
    if imag == 0.0 and real == 0.0:
        return complex_zero
    ...


If the entire docstring does not fit on the line, you can put the closing quotation marks on a separate line. Thus, it will be possible to use the Emacs command: fill-paragraph

Docstring Processing


Documentation line processing tools should remove the same number of indentation equal to the minimum indentation of all non-empty lines, starting from the second. Any indentation in the first line of the documentation is not significant and will be deleted. The relative indentation of later lines in the document line is retained. Empty lines should be removed from the beginning and end of the line of the document.

Since the code is much more accurate than words, the algorithm implementation is given here:

def trim(docstring):
    if not docstring:
        return ''
    #     (  Python)
    #      :
    lines = docstring.expandtabs().splitlines()
    #    (   ):
    indent = sys.maxsize
    for line in lines[1:]:
        stripped = line.lstrip()
        if stripped:
            indent = min(indent, len(line) - len(stripped))
    #   (   ):
    trimmed = [lines[0].strip()]
    if indent < sys.maxsize:
        for line in lines[1:]:
            trimmed.append(line[indent:].rstrip())
    #       :
    while trimmed and not trimmed[-1]:
        trimmed.pop()
    while trimmed and not trimmed[0]:
        trimmed.pop(0)
    #    :
    return '\n'.join(trimmed)

Translator's Note
, python3 sys.maxint sys.maxsize, .


The documentation in the following example contains two newlines and therefore has a length of three. The first and last lines are empty:

def foo ():
    """
       .
    """

We illustrate:

>>> print repr(foo.__doc__)
'\n        .\n    '
>>> foo.__doc__.splitlines()
['', '        .', '    ']
>>> trim(foo.__doc__)
'    .'

Thus, after processing, the following documentation lines will be equivalent:

def foo():
    """ 
     .
    """

def bar():
    """
     
     .
    """

Translator's Note
inspect, , : inspect.cleandoc(function.__doc__)


All Articles