2. Lexical analysis¶
A Python program is read by a parser. Input to the parser is a stream of tokens, generated by the lexical analyzer. This chapter describes how the lexical analyzer breaks a file into tokens.
Python reads program text as Unicode code points; the encoding of a source file can be given by an encoding declaration and defaults to UTF-8, see PEP 3120 for details. If the source file cannot be decoded, a SyntaxError is raised.
2.1. Line structure¶
A Python program is divided into a number of logical lines.
2.1.1. Logical lines¶
The end of a logical line is represented by the token NEWLINE. Statements cannot cross logical line boundaries except where NEWLINE is allowed by the syntax (e.g., between statements in compound statements). A logical line is constructed from one or more physical lines by following the explicit or implicit line joining rules.
2.1.2. Physical lines¶
A physical line is a sequence of characters terminated by an end-of-line sequence. In source files and strings, any of the standard platform line termination sequences can be used — the Unix form using ASCII LF (linefeed), the Windows form using the ASCII sequence CR LF (return followed by linefeed), or the old Macintosh form using the ASCII CR (return) character. All of these forms can be used equally, regardless of platform. The end of input also serves as an implicit terminator for the final physical line.
When embedding Python, source code strings should be passed to Python APIs using the standard C conventions for newline characters (the \n character, representing ASCII LF, is the line terminator).
2.1.3. Comments¶
A comment starts with a hash character ( # ) that is not part of a string literal, and ends at the end of the physical line. A comment signifies the end of the logical line unless the implicit line joining rules are invoked. Comments are ignored by the syntax.
2.1.4. Encoding declarations¶
If a comment in the first or second line of the Python script matches the regular expression coding[=:]\s*([-\w.]+) , this comment is processed as an encoding declaration; the first group of this expression names the encoding of the source code file. The encoding declaration must appear on a line of its own. If it is the second line, the first line must also be a comment-only line. The recommended forms of an encoding expression are
which is recognized also by GNU Emacs, and
which is recognized by Bram Moolenaar’s VIM.
If no encoding declaration is found, the default encoding is UTF-8. In addition, if the first bytes of the file are the UTF-8 byte-order mark ( b’\xef\xbb\xbf’ ), the declared file encoding is UTF-8 (this is supported, among others, by Microsoft’s notepad).
If an encoding is declared, the encoding name must be recognized by Python (see Standard Encodings ). The encoding is used for all lexical analysis, including string literals, comments and identifiers.
2.1.5. Explicit line joining¶
Two or more physical lines may be joined into logical lines using backslash characters ( \ ), as follows: when a physical line ends in a backslash that is not part of a string literal or comment, it is joined with the following forming a single logical line, deleting the backslash and the following end-of-line character. For example:
A line ending in a backslash cannot carry a comment. A backslash does not continue a comment. A backslash does not continue a token except for string literals (i.e., tokens other than string literals cannot be split across physical lines using a backslash). A backslash is illegal elsewhere on a line outside a string literal.
2.1.6. Implicit line joining¶
Expressions in parentheses, square brackets or curly braces can be split over more than one physical line without using backslashes. For example:
Implicitly continued lines can carry comments. The indentation of the continuation lines is not important. Blank continuation lines are allowed. There is no NEWLINE token between implicit continuation lines. Implicitly continued lines can also occur within triple-quoted strings (see below); in that case they cannot carry comments.
2.1.7. Blank lines¶
A logical line that contains only spaces, tabs, formfeeds and possibly a comment, is ignored (i.e., no NEWLINE token is generated). During interactive input of statements, handling of a blank line may differ depending on the implementation of the read-eval-print loop. In the standard interactive interpreter, an entirely blank logical line (i.e. one containing not even whitespace or a comment) terminates a multi-line statement.
2.1.8. Indentation¶
Leading whitespace (spaces and tabs) at the beginning of a logical line is used to compute the indentation level of the line, which in turn is used to determine the grouping of statements.
Tabs are replaced (from left to right) by one to eight spaces such that the total number of characters up to and including the replacement is a multiple of eight (this is intended to be the same rule as used by Unix). The total number of spaces preceding the first non-blank character then determines the line’s indentation. Indentation cannot be split over multiple physical lines using backslashes; the whitespace up to the first backslash determines the indentation.
Indentation is rejected as inconsistent if a source file mixes tabs and spaces in a way that makes the meaning dependent on the worth of a tab in spaces; a TabError is raised in that case.
Cross-platform compatibility note: because of the nature of text editors on non-UNIX platforms, it is unwise to use a mixture of spaces and tabs for the indentation in a single source file. It should also be noted that different platforms may explicitly limit the maximum indentation level.
A formfeed character may be present at the start of the line; it will be ignored for the indentation calculations above. Formfeed characters occurring elsewhere in the leading whitespace have an undefined effect (for instance, they may reset the space count to zero).
The indentation levels of consecutive lines are used to generate INDENT and DEDENT tokens, using a stack, as follows.
Before the first line of the file is read, a single zero is pushed on the stack; this will never be popped off again. The numbers pushed on the stack will always be strictly increasing from bottom to top. At the beginning of each logical line, the line’s indentation level is compared to the top of the stack. If it is equal, nothing happens. If it is larger, it is pushed on the stack, and one INDENT token is generated. If it is smaller, it must be one of the numbers occurring on the stack; all numbers on the stack that are larger are popped off, and for each number popped off a DEDENT token is generated. At the end of the file, a DEDENT token is generated for each number remaining on the stack that is larger than zero.
Here is an example of a correctly (though confusingly) indented piece of Python code:
The following example shows various indentation errors:
(Actually, the first three errors are detected by the parser; only the last error is found by the lexical analyzer — the indentation of return r does not match a level popped off the stack.)
2.1.9. Whitespace between tokens¶
Except at the beginning of a logical line or in string literals, the whitespace characters space, tab and formfeed can be used interchangeably to separate tokens. Whitespace is needed between two tokens only if their concatenation could otherwise be interpreted as a different token (e.g., ab is one token, but a b is two tokens).
2.2. Other tokens¶
Besides NEWLINE, INDENT and DEDENT, the following categories of tokens exist: identifiers, keywords, literals, operators, and delimiters. Whitespace characters (other than line terminators, discussed earlier) are not tokens, but serve to delimit tokens. Where ambiguity exists, a token comprises the longest possible string that forms a legal token, when read from left to right.
2.3. Identifiers and keywords¶
Identifiers (also referred to as names) are described by the following lexical definitions.
The syntax of identifiers in Python is based on the Unicode standard annex UAX-31, with elaboration and changes as defined below; see also PEP 3131 for further details.
Within the ASCII range (U+0001..U+007F), the valid characters for identifiers are the same as in Python 2.x: the uppercase and lowercase letters A through Z , the underscore _ and, except for the first character, the digits 0 through 9 .
Python 3.0 introduces additional characters from outside the ASCII range (see PEP 3131). For these characters, the classification uses the version of the Unicode Character Database as included in the unicodedata module.
Identifiers are unlimited in length. Case is significant.
The Unicode category codes mentioned above stand for:
Lu — uppercase letters
Ll — lowercase letters
Lt — titlecase letters
Lm — modifier letters
Lo — other letters
Nl — letter numbers
Mn — nonspacing marks
Mc — spacing combining marks
Nd — decimal numbers
Pc — connector punctuations
Other_ID_Start — explicit list of characters in PropList.txt to support backwards compatibility
All identifiers are converted into the normal form NFKC while parsing; comparison of identifiers is based on NFKC.
A non-normative HTML file listing all valid identifier characters for Unicode 14.0.0 can be found at https://www.unicode.org/Public/14.0.0/ucd/DerivedCoreProperties.txt
2.3.1. Keywords¶
The following identifiers are used as reserved words, or keywords of the language, and cannot be used as ordinary identifiers. They must be spelled exactly as written here:
2.3.2. Soft Keywords¶
New in version 3.10.
Some identifiers are only reserved under specific contexts. These are known as soft keywords. The identifiers match , case and _ can syntactically act as keywords in contexts related to the pattern matching statement, but this distinction is done at the parser level, not when tokenizing.
As soft keywords, their use with pattern matching is possible while still preserving compatibility with existing code that uses match , case and _ as identifier names.
2.3.3. Reserved classes of identifiers¶
Certain classes of identifiers (besides keywords) have special meanings. These classes are identified by the patterns of leading and trailing underscore characters:
Not imported by from module import * .
In a case pattern within a match statement, _ is a soft keyword that denotes a wildcard .
Separately, the interactive interpreter makes the result of the last evaluation available in the variable _ . (It is stored in the builtins module, alongside built-in functions like print .)
Elsewhere, _ is a regular identifier. It is often used to name “special” items, but it is not special to Python itself.
The name _ is often used in conjunction with internationalization; refer to the documentation for the gettext module for more information on this convention.
It is also commonly used for unused variables.
System-defined names, informally known as “dunder” names. These names are defined by the interpreter and its implementation (including the standard library). Current system names are discussed in the Special method names section and elsewhere. More will likely be defined in future versions of Python. Any use of __*__ names, in any context, that does not follow explicitly documented use, is subject to breakage without warning.
Class-private names. Names in this category, when used within the context of a class definition, are re-written to use a mangled form to help avoid name clashes between “private” attributes of base and derived classes. See section Identifiers (Names) .
2.4. Literals¶
Literals are notations for constant values of some built-in types.
2.4.1. String and Bytes literals¶
String literals are described by the following lexical definitions:
One syntactic restriction not indicated by these productions is that whitespace is not allowed between the stringprefix or bytesprefix and the rest of the literal. The source character set is defined by the encoding declaration; it is UTF-8 if no encoding declaration is given in the source file; see section Encoding declarations .
In plain English: Both types of literals can be enclosed in matching single quotes ( ‘ ) or double quotes ( " ). They can also be enclosed in matching groups of three single or double quotes (these are generally referred to as triple-quoted strings). The backslash ( \ ) character is used to escape characters that otherwise have a special meaning, such as newline, backslash itself, or the quote character.
Bytes literals are always prefixed with ‘b’ or ‘B’ ; they produce an instance of the bytes type instead of the str type. They may only contain ASCII characters; bytes with a numeric value of 128 or greater must be expressed with escapes.
Both string and bytes literals may optionally be prefixed with a letter ‘r’ or ‘R’ ; such strings are called raw strings and treat backslashes as literal characters. As a result, in string literals, ‘\U’ and ‘\u’ escapes in raw strings are not treated specially. Given that Python 2.x’s raw unicode literals behave differently than Python 3.x’s the ‘ur’ syntax is not supported.
New in version 3.3: The ‘rb’ prefix of raw bytes literals has been added as a synonym of ‘br’ .
New in version 3.3: Support for the unicode legacy literal ( u’value’ ) was reintroduced to simplify the maintenance of dual Python 2.x and 3.x codebases. See PEP 414 for more information.
A string literal with ‘f’ or ‘F’ in its prefix is a formatted string literal; see Formatted string literals . The ‘f’ may be combined with ‘r’ , but not with ‘b’ or ‘u’ , therefore raw formatted strings are possible, but formatted bytes literals are not.
In triple-quoted literals, unescaped newlines and quotes are allowed (and are retained), except that three unescaped quotes in a row terminate the literal. (A “quote” is the character used to open the literal, i.e. either ‘ or " .)
Unless an ‘r’ or ‘R’ prefix is present, escape sequences in string and bytes literals are interpreted according to rules similar to those used by Standard C. The recognized escape sequences are:
Python Syntax
В предыдущей статье рассмотрели достоинства и недостатки ЯП Python, установили интерпретатор python3 и написали первую программу Hello, world!.
В сегодняшней статье расммотрим синтаксис языка, модель динамической типизации.
Синтаксис языка Python
Идентификаторы
Идентификаторы в Python — это имена, используемые для определения переменных, функций, классов, модулей и других объектов. Идентификатор начинается с букв A-Z или a-z, либо знака подчеркивания (_), после чего следует ноль или больше букв, знаков подчеркивания или цифр от 0 до 9.
Никогда не создавайте свою собственную переменную с именем (_), так как это имя зарезервировано самим интерпретатором.
В идентификаторах Python не используются знаки @, $ и %. Так же – Python чувствителен к регистру символов, т.е. Manpower и manpower являются двумя различными именами (идентификаторами).
Зарезервированные имена
В списке ниже приведены имена, которые зарезервированы в Python, и их использование не допускается в использовании определения констант, переменных или любых других пользовательских именах. Все зарезервированные слова содержат только строчные буквы:
| and | del | from | not | while |
| as | elif | global | or | with |
| assert | else | if | pass | yield |
| break | except | import | ||
| class | exec | in | raise | |
| continue | finally | is | return | |
| def | for | lambda | try |
Список зарезервированых имен можно так же получить следующим образом:
Строки и отступы
Одно из самых важных замечаний для тех, кто начал изучать Python – это то, что в нём при обозначении границ блоков кода для классов и функций, а так же для управления потоками, не используются привычные некоторым фигурные скобки. Вместо этого – в Python используются отступы строк.
Количество отступов в начале строки не имеет значения, но все операторы внутри такого блока должны иметь их одинаковое количество.
Например, оба блока в примере ниже выполнены правильно:
А вот второй блок в следующем примере – приведёт к ошибке интерпретатора IndentationError: unexpected indent:
Таким образом, все линии, имеющие одинаковое количество отступов от начала строки будут формировать блок кода.
Многострочные операторы
Операторы и операнды в Python как правило заканчиваются новой строкой. Однако, есть возможность использовать знак продолжения строки (\) для обозначения того, что строка продолжается. Например:
Операнды, заключённые в скобки [], <> или () не нуждаются в использовании такого символа. Например:
Что бы представлять себе разницу между “оператором” и “операндом” при выполнении “операции” – посмотрите на эту картинку:
Кавычки в Python
В Python используются одинарные (‘), двойные (") и тройные (»’ или """) кавычки для обозначения строковых литералов (или просто – строк).
Тройные кавычки могут использоваться для охвата многострочного текста.
Комментарии в Python
Хеш-тег (#), который не находится внутри строки задаёт начало комментария. Все символы после # и до конца строки являются частью комментария, и Python игнорирует их.
Приведённый выше код даст такой результат:
Комментарии так же можно размещать и на одной строке после операторов или выражения, например:
Многострочные комментарии можно создать так:
Пустые строки
Пустые строки, или строки содержащие только пробелы, или строки с комментариями, игнорируются интерпретатором.
В интерактивной сессии интерпретатора, необходимо ввести пустую строку для завершения многострочного оператора.
Более подробно о том, как правильно оформлять код Python можно прочитать в PEP8!
PEP (python enhanced proposal) — заявки на улучшение языка Python.
Модель динамической типизации
В одном из примеров мы не объявляли тип переменной либо её саму:
У вас может возникнуть вопрос, как же интерператор Python узнает, что речь идет о строке? И вообще, как Python узнает, что есть что?
Для того, чтобы ответить на эти вопросы, необходимо рассмотреть как работает динамическая типизация в Python. Типы данных в Python определяются автоматически во время выполнения, а не в результате объявлений в программном коде. Это означает, что вам не требуется заранее объявлять переменные (эту концепцию проще понять, если иметь в виду, что все сводится к переменным, объектам и ссылкам между ними).
Создание переменной
Переменная (т.е. имя или идентификатор), такая как name, создается автоматически, когда в программном коде ей впервые присваивается некоторое значение. Все последующие операции присваивания просто изменяют значение, ассоциированное с уже созданным именем.
Типы переменных
Переменные не имеют никакой информации о типе или ограничениях, связанных с ними. Понятие типа присущие объектам, а не именам. Переменные универсальны по своей природе — они всегда являются всего лишь ссылками на конкретные объекты в конкретные моменты времени.
Использование переменной
Когда переменная участвует в выражении, ее имя замещается объектом, на который она в настоящий момент ссылается, независимо от того, что это за объект. Кроме того, прежде чем переменную можно будет использовать, ей должно быть присвоено значение — использование неицициализированной переменной приведет к ошибке (NameError: name ‘name’ is not defined).
Для того чтобы понимать что происходит при присваивании некого значения переменной, рассмотрим такой пример:
Python выполнит эту инструкцию в три этапа, концептуально.
- Cоздается объект, представляющий число 3.
- Создается пременная a, если она еще отсутствует.
- В переменную a записывается ссылка на вновь созданный объект, представляющий число 3.
Информация о типе хранится в объекте, но не в переменной.
Допустим, у нас есть следующий пример:
Как уже указывалось ранее, имена не имеют типов, тип — это свойство объекта, а не имени. В предыдущем листинге просто изменяется ссылка на объект. Все что можно сказать о перменных в языка Python — это то, что они создаются на конкретные объекты в конкретные моменты времени.
Объекты знают, к какому типу они относятся, — каждый объект содержит поле, в котором хранится информация о его типе. Целочисленный объект 3, например, будет содержать значение 3 плюс информацию, которая сообщит интерпретатору Python, что объект является целым числом (строго говоря — это указатель на объект с названием int). Описатель типа для строки ‘spam’ указывает на строковой тип (с именем str). Поскольку информация о типе хранится в объектах, ее не нужно хранить в переменных.
У кого-то может возникнуть вопрос: что происходит с прежними значениями, когда выполняется новое присваивание? Например, что произойдет с объектом 3 после выполнения следующих инструкций:
Основная выгода от сборки мусора состоит в том, что вы может свободно распоряжаться объектами, не будучи обязаны освбождать память в своем сценарии.
Когда имя ассоциируется с новым объектом, интепретатор Python освобождает память, занимаемую предыдущим объектом (если на него не ссылается какое-либо другое имя или объект). Такое автоматическое освобождение памяти, занимаемой объектами, называется сборкой мусора (garbage collection).
Разделяемые ссылки
До сих пор мы рассматривали вариант, когда ссылка на объект присваивается единственной переменной. Теперь введем в действие еще одну переменную и посмотрим, что происходит с именами и объектами в это случае:

В языке Python это называется разделяемая ссылка — несколько имен ссылаются на один и тот же объект.
Далее добавим еще одну инструкцию:
В результате выполнения этой инструкции создается новый объект, представляющий строку ‘spam’, а ссылка на него записывается в переменную a. Однако эти действия не оказывают влияния на переменную b — она по-прежнему ссылается на первый объект, целое число 3. В результате схема взаимоотношений приобретает вид:

То же самое произошло бы, если бы ссылка на объект ‘spam’ вместо переменной a была присвоена переменной b — изменилась бы только переменная b, но не а. Аналогичная ситуация возникает, даже если тип объекта не изменяется. Например, рассмотрим следующие три инструкции:
В этой последовательности происходит те же самые события: интепретатор Python создает переменную a и записывает в нее ссылку на объект 3. После этого он создает переменную b и записывает в нее ту же ссылку, что хранится в переменной a. Наконец, последняя инструкция создает совершенно новый объект (в данном случае — целое число 5, которое является результатом выполнения операции сложения). Это не приводит к изменению переменной b. В действительности нет никакого способа перезаписать значение объекта 3, целые числа относятся к категории неизменяемых (подробнее о категориях и типов данных далее), и поэтому эти объекты невозможно изменить.
Разделяемые ссылки и изменяемые объекты
Как будет показано дальше в этом цикле статей, существуют такие объекты и операции, которые приводят к изменению самих объектов. Например, операции присваивания значения элементу списка фактически изменяют сам список вместо того, чтобы создавать совершенно новый объект списка. При работе с объектами, допускающими такие изменения, необходимо быть особенно внимательными при использовании разделяемых ссылок, так как изменение одного имени может отразиться на других именах.
Возьмем в качестве примера объекты списков (будут рассмотрены подробно в следующей части). Списки, поддерживают возможность присваивания значений элементам, — это просто коллекция объектов, которые в программном коде записываются как литералы в квадратных скобках:
В данном случае L1 — это список, содержащий объекты 2, 3 и 4. Доступ к элементам списка осуществляется по их индексам; так, L1[0] — ссылается на объект 2, т.е. на первый элемент в списке L1. Cписки являются полноценными объектами, такими же, как целые числа и строки. После выполнения двух приведенных выше инструкций L1 и L2 будут ссылаться на один и тот же объект, так же, как переменные a и b в примере выше. Точно так же, если теперь добавить еще одну инструкцию:
Переменная L1 будет ссылаться на другой объект, а L2 по-прежнему будет ссылаться на первоначальный список. Однако если синтаксис последней инструкции немного изменить, эффект получится другим:
Здесь мы не изменяем сам объект L1, изменяется компонент объекта, на который ссылается L1. Данное изменение затронуло часть самого объекта списка. Поскольку объект списка разделяется разными переменными, то изменения в самом списке затрагивают не только L1, т.е. следует понимать, что такие изменения могут сказываться в других частях программы. В этом примере изменения обнаруживаются также в переменной L2, потому что она ссылается на тот же самый объект, что и L1. Здесь мы фактически не изменяли L2, но значение этой переменной изменилось.
Это поведение по умолчанию: если вас оно не устраивает, можно потребовать от интерпретатора, чтобы вместо создания ссылок он выполнял копирование объектов. Скопировать список можно несколькими способами, включая встроенную функцию list и модуль copy из стандартной библиотеки. Однако самым стандартным способом копирования является получение среза (так же будет рассмотрено в следующих частях) от начала и до конца списка.
Будьте внимательны, что способ, основанный на получении среза, неприменим в случае с другими изменяемым базовым типом — со словарем (будет рассмотрен подробно в следущей части), потому что словарь не является последовательностью. Чтобы скопировать словарь, необходимо воспользоваться методом X.copy(). Следует также отметить, что модуль copy из стандартной библиотеки имеет в своем составе универсальную функцию, позволяющую копировать объекты любых типов, включая вложенные структуры (например, словари с вложенными списками).
Разделяемые ссылки и равенство
Возможность сборки мусора, описанная ранее, может оказаться более принципиальным понятием, чем литералы для объектов некоторых типов.
Так как интерпретатор Python кэширует и повторно использует малые целые числа и небольшие строки, объект 42 скорее всего не будет уничтожен. Он, вероятнее всего, останется в системной таблице для повторного использования, когда вы вновь сгенерируете число 42 в программном коде. Однако большинство объектов уничтожаются немедленно, как только будет потеряна последняя ссылка, особенно те, к которым применение механизма кэширования не имеет смысла.
Согласно модели ссылок в языке Python, существует два разных способа выполнять проверку равенства.
Первый способ, основанный на использовании оператора ==, проверяет, равны ли значения объектов. В языке Python практически всегда используется именно этот способ. Второй способ, основанный на использовании оператора is, проверяет идентичность объектов. Он возвращает значение True, только если оба имени ссылаются на один и тот же объект, вследствие этого он является более строгой формой проверки равенства.
На самом деле оператор is просто сравнивает указатели, которые реализуют ссылки, и тем самым может использоваться для выявления разделяемых ссылок в программном коде. Он возвращает значение False, даже если имена ссылаются на эквивалентные, но разные объекты, как, например, в следующем случае, когда выполняются два различных литеральных выражения:
Посмотрим, что происходит, если те же самые действия выполняются над малыми целыми числами:
В этом примере переменные x и y должны быть равны, но не эквивалентны, потому что было выполнено два разных литеральных выражения. Однако из-за того, что малые целые числа и строки кэшируются и используются повторно, оператор is сообщает, что переменные ссылаются на один и тот же объект.
Фактически если вы действительно хотите взглянуть на работу внутренних механизмов, вы всегда можете запросить у интерпретатора количество ссылок на объект: функция getrefcount из стандартного модуля sys возвращает значение поля счетчика ссылок в объекте.
На этом сегодняшняя статья окончена. В следующий раз рассмотрим типы данных.
Комментирование и документация кода в Python

Документирование кода на ранних этапах разработки имеет гораздо большее значение, чем может показаться на первый взгляд. Эта тема также связана с добавлением полезных комментариев к коду. Когда вы погружаетесь в разработку программы, вы можете неосознанно присвоить своим переменным и функциям весьма странные и непонятные названия. Таким образом, через некоторое время, вернувшись к коду, вы потратите огромное количество времени, пытаясь разобраться, что к чему.
Содержание статьи
Делая свой код самодокументирующимся (то есть используя информативные имена) и добавляя комментарии, вы сделаете программу более читабельной для себя и для всех остальных, кто может её использовать. Это также облегчит обновление и рефакторинг кода!
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Telegram Чат & Канал
Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
В данной статье вы познакомитесь со следующими темами:
- Комментарии;
- Строки документации — Docstrings;
- PEP8 — Руководство по написанию кода;
- Другие полезные инструменты для документирования вашего кода.
Давайте начнем с комментариев.
Комментарии в коде на Python
Комментарии — это подсказки, которые предназначены для вас, а не для компьютера. Комментарий это, по сути, заметка, которая объясняет, что происходит в рассматриваемой части кода. Они используются, чтобы объяснить, почему вы что-то сделали или как работает тот или иной фрагмент кода. Когда вы только начинаете программировать, будет не лишним оставлять много комментариев, к которым можно будет потом вернуться. Как только вы научитесь правильно и удобно именовать свои функции и переменные, вы поймете, что многие комментарии вам больше не нужны.
Тем не менее, комментарии все равно рекомендуется использовать. Они особенно полезны для сложного кода, который нелегко понять с первого взгляда. В зависимости от компании, в которой вы работаете, вы также можете использовать комментарии для документирования багов. Например, если вы исправили ошибку, вы можете добавить комментарий, который объясняет, в чем именно она заключается.
В Python комментарии создаются с помощью знака # , за которым следует какой-либо описательный текст.
Далее представлен пример комментария в Python:
В приведенном выше коде показано, как создать простой комментарий. При выполнении кода, Python увидит символ # и проигнорирует весь следующий за ним текст. По сути, Python пропустит эту строку и попытается выполнить вторую.
Этот комментарий помечен как «плохой комментарий». Хотя он хорош для демонстрационных целей, но он не описывает код, который следует далее. По этой причине он не является полезным. Хорошие комментарии должны объяснять и описывать последующий код, его цели или что-то еще. Комментарии — это своеобразная документация вашего кода. Если они не предоставляют никакой полезной информации, то их следует удалить.
Вы также можете создавать комментарии на строке с кодом:
Здесь вы снова присваиваете переменной x значение 10, но затем добавляете символ # , который позволяет добавить комментарий к коду. Это полезно в тех случаях, когда необходимо объяснить конкретную строку кода. Если вы назвали свою переменную каким-то логическим и интуитивно понятным именем, то, скорее всего, комментарий вообще не понадобится.
Как закомментировать и раскомментировать строки кода
В будущем вы довольно часто будете сталкиваться с таким понятием, как «закомментированный код«. Это практика добавления символа # в начале вашего кода. Таким образом, можно на всякий случай убрать какой-то кусок кода, сделав его на данный момент нерабочим.

К примеру, у вас может быть следующая строка кода:
Если вы хотите закомментировать её, это можно сделать следующим образом:
Вы можете закомментировать код в тех случаях, когда пробуете различные решения, но не хотите удалять предыдущие варианты программы. Python будет игнорировать закомментированный код, позволяя вам попробовать разнообразные пути решения задачи. Большинство редакторов кода IDE (и текстовых редакторов) предоставляют возможность выделять несколько строк и закомментировать весь блок кода.
Горячие клавиши для комментирования куса кода: (выделить нужный участок кода) + Ctrl + /
Многострочные комментарии в Python
Некоторые языки программирования, к примеру С++, предоставляют возможность создания многострочных комментариев. Для создания многострочных комментариях вы спокойно можете использовать тройные кавычки.
Далее представлен пример многострочного комментария на Python:
При использовании строк с тройным кавычками вы можете создать docstring (строки документации). По сути, мы уже это сделали когда добавили многострочный комментарии для функции test() .
Давайте выясним, что это такое, и как оно используется!
Для чего используется docstring?
В Python существует концепция PEP, или Python Enhancement Proposal. PEP представляют собой предложения или новые возможности для языка Python, которые обсуждаются и согласовываются руководящим советом Python.
PEP 257 описывает соглашения о docstring. Вы можете прочитать его, если вам нужна более подробная информация. Если обобщить, то docstring — это строковый литерал, который должен быть сразу после определения названия для модуля, функции, класса или метода.
docstring создается с помощью трех двойных кавычек.
В Python docstring игнорируются. Они не могут быть выполнены. Однако, когда вы добавляете docstring к модулю, функции и так далее, то данная строка становится специальным атрибутом, к которому можно получить доступ через __doc__ .
docstring можно использовать как для однострочных, так и для многострочных строк.
Далее дан пример однострочной строки:
Однострочная docstring является простой строкой текста.
Далее представлена строка docstring, используемый в функции:
В приведенном выше коде показано, как можно добавить docstring в функцию. Хорошая строка docstring описывает, что должна сделать функция.
На заметку: Хотя три двойные кавычки являются рекомендуемым стандартом, три одинарные кавычки, одни двойные кавычки и одни одинарные кавычки также работают (но одни двойные и одинарные кавычки могут содержать только одну строку, а не несколько).
Теперь давайте узнаем о создании программы в соответствии с руководством по написанию кода на Python.
PEP 8 — руководство по написанию кода на Python
Руководство по написанию кода — это документ, в котором описывается хорошая практика программирования, обычно применительно к одному языку. В некоторых компаниях существуют специальные руководства по стилю, которым сотрудники должны следовать независимо от того, какой язык программирования они используют.
Руководство по написанию кода Python было создано еще в 2001 году и получило название PEP8. В нем указаны соглашения по программированию на языке Python. За прошедшие годы текст несколько раз обновлялся.
Если вы планируете часто использовать Python, вам стоит ознакомиться с этим руководством. Оно поможет вам писать более качественный код на языке Python. Кроме того, если вы хотите внести вклад в развитие самого языка Python, ваш код должен соответствовать стилю руководства. Следование руководству сделает ваш код более легким для чтения и понимания. Это поможет вам и всем остальным, кто будет использовать ваш код в будущем.
Однако запомнить все правила может быть непросто. К счастью, некоторые бесстрашные разработчики создали определенные утилиты, которые могут помочь!
Полезные инструменты для документирования вашего кода
Существует множество инструментов, которые можно использовать для написания отличного кода. Вот всего несколько из них:
-
— Проверяет, если ваш код соответствует стандарту PEP8; — Инструмент для углубленного статического тестирования кода, который находит общие проблемы в коде; — Еще один инструмент для статического тестирования кода; — Обертка для PyFlakes, pycodestyle и McCabe; — Форматировщик кода, который в основном следует стандарту PEP8.
Вы можете использовать эти инструменты, чтобы найти проблемные места в вашем коде. Pylint, PyFlakes и flake8 кажутся мне наиболее полезными. Black пригодится, если вы работаете в команде и хотите, чтобы код каждого сотрудника был написан в одном формате. Можете добавить Black в свой список инструментов форматирования кода.
Более продвинутые IDE для Python делают определенные проверки в режиме реального времени. Например, PyCharm автоматически проверяет многие проблемы, которые фиксируют эти инструменты. WingIDE и VS Code также обеспечивают некоторую проверку кода. Можете просто попробовать различные IDE и посмотреть, что подойдет вам лучше всего.
Подведем итоги
В Python есть несколько различных способов документирования кода. Вы можете использовать комментарии, чтобы объяснить одну или несколько строк кода. Их следует использовать умеренно и по мере необходимости. Вы также можете использовать docstring, чтобы документировать модули, функции, методы и классы.
Вам также следует ознакомиться с руководством по программированию на Python, которое можно найти в PEP8. Это поможет разобраться в принципах хорошего программирования на Python. Существует несколько других руководств по стилю написания кода на Python. Например, руководство по стилю от Google или руководство по стилю Python от NumPy. Иногда ознакомление с различными руководствами может помочь развить свой собственный хороший стиль программирования.
Мы также познакомились с несколькими инструментами, которые можно использовать для улучшения вашего кода. Если у вас есть время, я советую вам ознакомиться с PyFlakes или Flake8, так как они могут помочь найти общие проблемы в вашем коде.

Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.
Инструкции, отступы и комментарии в Python
Инструкции, которые может выполнять интерпретатор Python, называются операторами. Например, a = 1 — это оператор присваивания. Оператор if , оператор for , оператор while и т. д. — это другие типы операторов, которые мы обсудим позже.
Многострочные инструкции
В Python для окончания инструкции используют символ новой строки. Но можно разбить инструкцию на несколько строк символом продолжения строки (\). Например:
Это явное продолжение строки. В Python продолжение строки выполняется внутри круглых ( ) , квадратных [ ] и фигурных скобок < >. Например, так мы можем реализовать показанную выше многострочность:
Здесь круглые скобки ( ) неявно продолжают строку. То же самое с [ ] и < >. Например:
Мы также можем поместить несколько выражений в одну строку с помощью точки с запятой, как показано ниже:
Отступы
Большинство языков программирования, таких как C, C ++ и Java, используют фигурные скобки < >для определения блока кода. Однако Python использует отступы.
Блок кода (тело функции, цикла и т. д.) начинается с отступа и заканчивается первой строкой без отступа. Размер отступа зависит от вас, но он должен быть одинаковым на протяжении всего блока.
Как правило, для отступов используют четыре пробела или табуляцию. Вот пример:
Применение отступов в Python делает код аккуратным и чистым. Программы благодаря отступам выглядят последовательными. С ними блоки кода визуально легче отличать друг от друга.
Сравните:
Оба варианта допустимы и сделают одно и то же, но первый вариант — читабельнее.
Неправильный отступ приведет к ошибке IndentationError .
Комментарии
Комментарии очень важны при написании программы. Они описывают, что происходит внутри программы, чтобы человеку, который читает код, было проще разобраться в нем.
Вы можете забыть детали программы, написанной даже месяц назад. Поэтому всегда полезно уделять время на пояснение основных моментов в комментариях.
В Python для комментариев используется символ решетки (#).
Комментарий заканчивается символом новой строки. Интерпретатор Python игнорирует комментарии.
Многострочные комментарии
В Python можно использовать многострочные комментарии. Один из способов — использовать символ решетки (#) в начале каждой строки. Например:
Можно поступить иначе — использовать тройные кавычки: »’ или «»» .
Тройные кавычки обычно используются для многострочных строк. Но их также можно использовать для многострочных комментариев. Если они не являются строками документации, они не создают никакого дополнительного кода.
Строки документации (docstrings) в Python
Docstring — это сокращение от documentation string (строка документации).
Строки документации в Python — это строковые литералы, которые появляются сразу после определения функции, метода, класса или модуля.
При написании строк документации используются тройные кавычки. Например:
Строки документации появляются сразу после определения функции, класса или модуля. Это и отличает их от многострочных комментариев, написанных с использованием тройных кавычек.
Строка документации связана с объектом как его атрибут __doc__ .
Так что мы можем получить доступ к строкам документации функции с помощью следующих строк кода: