Готовый перевод The Python Language Reference / Справочник по языку Python: 7. Compound statements
7. Составные инструкции
Составные инструкции содержат другие инструкции или их группы. Они влияют, или прямо контролируют исполнение содержащихся инструкций каким-либо образом. Как правило составные инструкции состоят из нескольких строк, однако в простых выражениях составная инструкция может целиком размещаться в одной строке.
Инструкции «if», «while» и «for» реализуют стандартные конструкции управления потоком исполнения. «try» определяет для определённой группы выражений обработчик исключения и/или код ликвидации последствий, тогда как инструкция «with» позволяет исполнять инициализирующий и завершающий код соответственно до и после определённого кода. Определения функций и классов синтаксически также являются составными инструкциями.
Составные инструкции состоят из одной или более «групп» . Группа состоит из «заголовка» и «содержимого» . Все «заголовки» групп одной составной инструкции находятся на одном уровне отступов. Каждый «заголовок» группы начинается с однозначно идентифицирующего ключевого слова и заканчивается двоеточием. Инструкции «содержимого» являются подконтрольными в группе . «Содержимое» может быть одной или более простыми инструкциями разделенными точкой с запятой в той же строке, что и «заголовок» , после двоеточия «заголовка» , или же может быть одной или более инструкций, идущих в отдельных строках с отступом. Только последняя форма содержимого группы может содержать вложенные составные инструкции. Следующий пример недопустим, главным образом потому, что не ясно, группе которого «if» будет относиться группа следующего «else» :
if test1: if test2: print(x)
К тому же заметьте, что (в данном контексте) точка-с-запятой связывается сильнее, чем двоеточие, таким образом в следующем примере исполняются или все инструкции «print()» , или ни одной :
if x < y < z: print(x); print(y); print(z)
В итоге :
compound_stmt ::= if_stmt
| while_stmt
| for_stmt
| try_stmt
| with_stmt
| funcdef
| classdef
suite ::= stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
statement ::= stmt_list NEWLINE | compound_stmt
stmt_list ::= simple_stmt (";" simple_stmt)* [";"]
Заметьте, что инструкции всегда заканчиваются признаком «NEWLINE» , после которого может идти «DEDENT» . Также отметьте, что необязательные ветви в условиях всегда начинаются с такого ключевого слова, по которому ясно, что это именно продолжение инструкции необязательною ветвью, и с этого слова не может начинаться новая инструкция. Проблема “оторванных” «else» решена в Питоне через обязательность отступов для вложенных «if» .
В следующих описаниях грамматических правил для удобочитаемости каждая формула размещается с новой строки.
7.1 Инструкция «if»
Инструкция «if» служит для исполнения по условию :
if_stmt ::= "if" expression ":" suite
( "elif" expression ":" suite )*
["else" ":" suite]
Инструкция «if» выбирает только одну вложенную группу инструкций, вычисляя выражения-условия по очереди до первого со значением «True» (смотрите раздел «Логические (булевы) операции» ) , затем соответствующая вложенная группа исполняется (и больше не вычисляются другие выражения-условия и не выполняются другие группы) . Если все выражения-условия имеют значение «False» , то вложенная группа ветви «else» выполняется, если присутствует.
7.2 Инструкция «while»
Инструкция «while» используется для циклического исполнения пока выражение истинно :
while_stmt ::= "while" expression ":" suite ["else" ":" suite]
Инструкция «while» циклически проверяет выражение-условие, и если оно истинно – выполняет первую вложенную группу, а если оно ложно – (даже если это происходит при первой же проверке) цикл завершается и вложенная группа ветви «else» выполняется, если присутствует.
Исполнение инструкции «break» в первой группе прекращает цикл без исполнения ветви «else» . Инструкция «continue» в первой группе пропускает остаток этой группы, и происходит переход обратно к проверке выражения-условия.
7.3 Инструкция «for»
Инструкция «for» используется для того, чтобы перебирать последовательно элементы последовательности (например текстовые данные, «кортежи» , списки) или другого перечислимого объекта :
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
Список выражений «expression_list» вычисляется только один раз – он должен давать в результате итерируемый объект, для которого создаётся итератор. Вложенный блок затем исполняется по одному разу для каждого элемента, выданного итератором в порядке увеличения индексов. Каждый такой выданный итератором элемент назначается списку целей в соответствии со стандартными правилами назначения (смотрите раздел 6.2. «Инструкции назначения») , и затем уже́ вложенный блок исполняется. Когда эти элементы кончаются (в самом начале, если последовательность пустая, или когда итератор инициирует исключение «StopIteration» ) , то исполняется блок инструкций ветви «else» , если таковая присутствует, и цикл прекращается.
Инструкция «break» , исполненная в основной ветви («for») , прекращает цикл без исполнения ветви «else» . Инструкция «continue» , исполненная в основной ветви («for») , пропускает оставшиеся инструкции блока и, если итерируемые элементы ещё есть – переходит к новому исполнению блока со следующим элементом, а иначе переходит к ветви «else» .
Внутри вложенного блока можно изменять значение переменных из списка целей, и это ни как не повлияет на их значение, когда при следующем проходе им будет назначено значение очередного элемента.
Имена из списка целей не удаляются после окончания цикла, но, если последовательность пустая, то этим именам вообще не будет назначено значение (и, если переменные не существовали, то и не будут созданы) . Подсказка : встроенная функция «range()» возвращает итератор целых чисел, который можно использовать для эмулирования эффекта Паскалевского «for i := a to b do» , например, «list(range(3))» возвращает список «[0, 1, 2]» .
Замечание. Есть тонкость, когда итерируемая последовательность изменяется внутри цикла (это может произойти только с изменяемыми последовательностями, например списком) . Для отслеживания того, какой элемент будет использован следующим, – используется внутренний счётчик, увеличиваемый на единицу при каждом проходе. Когда он достигает длинны последовательности – цикл прекращается. Это значит, что если внутри блока цикла удаляется текущий (или один из предыдущих) элемент последовательности, то элемент, который должен был быть выдан следующим будет пропущен, поскольку он получит индекс элемента, обрабатываемого в данный момент. Таким же образом, если внутри блока цикла в последовательность добавляется элемент до текущего элемента, то текущий элемент будет обработан ещё раз на следующем проходе цикла. Это может приводить к очень неприятным ошибкам, которых можно избежать, если для последовательности делать временную копию, с помощью среза всей последовательности, например :
<pre style="margin-bottom: 0em; margin-top: 0em;">for x in a[:]:<br /> if x < 0: a.remove(x)</pre>
7.4. Инструкция «try»
Инструкция «try» задаёт обработчики исключения и/или завершающий код для блока инструкций :
<code>try_stmt ::= try1_stmt | try2_stmt
try1_stmt ::= "try" ":" suite
("except" [expression ["as" target]] ":" suite)+
["else" ":" suite]
["finally" ":" suite]
try2_stmt ::= "try" ":" suite
"finally" ":" suite</code>
Ветвь «<code>except</code>» задаёт один или более обработчиков исключений. Если не происходит ни одного исключения в соответствующей ветви «<code>try</code>» , то никакой из этих обработчиков не вызывается. Когда случается какое-либо исключение в соответствующей ветви «<code>try</code>» , то начинается поиск обработчика этого исключения. При этом поиске просматриваются последовательно все блоки «<code>except</code>» пока не встретится первый блок соответствующий произошедшему исключению. Если задан блок «<code>except</code>» без указания исключения , который подразумевает любое исключение, то его логично указывать последним. Для инструкции «<code>except</code>» с выражением – это выражение вычисляется, и если объект-результат является “совместимым” с обрабатываемым исключением, то данный блок «<code>except</code>» соответствует данному исключению. Объект совместим с данным исключением, если он является классом или базовым классом данного исключения, или же является кортежем, содержащим объект, совместимый с данным исключением.
Если не найдено ни одного блока «<code>except</code>» , соответствующего исключению, то поиск продолжается в окружающем коде и по стеку вызовов.
Исключение передаётся вверх по стеку вызовов только если отсутствует блок «<code>finally</code>» , такой, который нейтрализует данное исключение.
Если при вычислении выражения у само́й инструкции «<code>except</code>» возникает исключение, то обработка текущего исключения (возникшего внутри блока «<code>try</code>» , к которому относится данная инструкция «<code>except</code>» ) отменяется, и начинается поиск обработчика для этого нового исключения в объемлющем коде и по стеку вызовов (тоесть, считается, что исключение вызвала вся конструкция «<code>try</code>» ) .
Если найдена соответствующая ветвь «<code>except</code>» , то внутри этой ветви данное исключение назначается получателю, указанному после ключевого слова «<code>as</code>» , если таковое присутствует, и затем блок кода этой ветви «<code>except</code>» исполняется. Все ветви «<code>except</code>» должны иметь исполнимый блок. Когда исполнение этого блока завершается – обработка данного исключения завершена, и исполнение продолжается уже́ обычным образом после всей конструкции «<code>try</code>» . (Это также значит, что если есть два вложенных обработчика для одного вида исключения, то когда оно происходит внутри внутренней ветви «<code>try</code>» – внешний обработчик не получит этого исключения.)
Если исключение назначается переменной, указанной после ключевого слова «<code>as</code>» , то она автоматически удаляется при завершении этого блока «<code>except</code>» , как если бы
<code>except E as N:
foo</code>
транслировалось в
<code>except E as N:
try:
foo
finally:
del N</code>
Из этого следует, что если нужно иметь возможность обращаться к данному объекту-исключению после завершения блока «<code>except</code>» , то нужно назначить это исключение ещё какому-либо имени. Причиной этого является то, что исключения со связанной с ними трассировкой образуют циклические ссылки с кадром стека, из-за чего все локальные переменные в этом кадре будут сохраняться до следующего сбора мусора.
Перед исполнением блока кода ветви «<code>except</code>» информация об исключении записывается в модуль «<code>sys</code>» и её можно получить с помощью «<code>sys.exc_info()</code>» . «<code>sys.exc_info()</code>» возвращает тройной кортеж, содержащий : «<code>exc_type</code>» – класс данного исключения; «<code>exc_value</code>» – экземпляр исключения; «<code>exc_traceback</code>» – объект трассировки (смотрите раздел об иерархии стандартных типов) указывающий место программы, в котором произошло исключение. Значения «<code>sys.exc_info()</code>» восстанавливаются в их предыдущее значение при возвращении из функции обработки исключения.
Необязательная ветвь «<code>else</code>» исполняется только если и когда происходит выход из блока «<code>try</code>» в связи с его исчерпанием, а не в связи с исключением или исполнением инструкций «<code>return</code>» , «<code>continue</code>» или «<code>break</code>» . Исключения в такой ветви «<code>else</code>» не обрабатываются идущими перед нею ветвями «<code>except</code>» (относящимися к той же конструкции «<code>try</code>») , а являются исключением, возникшим в целой этой конструкции «<code>try</code>» (и обрабатываются во внешнем коде) .
-
Если присутствует ветвь «<code>finally</code>» , то она определяет завершающий (зачищающий) обработчик. Выполняется ветвь «<code>try</code>» , а также все ветви «<code>except</code>» и «<code>else</code>» . Если в любой из них происходит исключение, и оно не обработано, то оно временно сохраняется. Затем выполняется ветвь «<code>finally</code>» . Затем, если было сохранено исключение, оно вызывается заново по завершении ветви «<code>finally</code>» . Если в ветви «<code>finally</code>» происходит исключение или исполняется инструкция «<code>return</code>» или «<code>break</code>» , то сохранённое исключение теряется. Информация об сохранённом исключении не доступна программе во время исполнения ветви «<code>finally</code>» .
Если в ветви «<code>try</code>» исполняется инструкция «<code>return</code>» или «<code>break</code>» , то ветвь «<code>finally</code>» тоже исполняется перед выходом из всей конструкции «<code>try...finally</code>» . В ветви «<code>finally</code>» инструкция «<code>continue</code>» недопустима. (Проблема в текущей реализации – это ограничение может быть снято в будущем.)
Дополнительная информация об исключениях есть в разделе “Исключения” , а об использовании инструкции «<code>raise</code>» для вызова исключений – в разделе “Инструкция «raise»” .
-
7.5. Инструкция «<code>with</code>»
Инструкция «<code>with</code>» используется для “оборачивания” исполнения блока методами, определёнными менеджером контекста (смотрите раздел “Менеджеры контекста инструкции «<code>with</code>» ” ) . Это позволяет общим схемам использования «<code>try...except...finally</code>» быть инкапсулированными для удобного повторного использования.
«<code>with_stmt ::= "with" with_item ("," with_item)* ":" suite</code>»
«<code>with_item ::= expression ["as" target]</code>»
Исполнение инструкции «<code>with</code>» с одним “элементом” происходит так:
Выражение контекста («<code>with_item</code>») вычисляется, чтобы получить менеджер контекста.
Вызывается метод «<code>__enter__()</code>» этого менеджера контекста.
Если присутствует цель назначения («<code>target</code>») , то возвращаемое от «<code>__enter__()</code>» значение назначается этой цели.
Замечание
Инструкция «<code>with</code>» гарантирует, что если метод «<code>__enter__()</code>» выполняется без ошибки, то обязательно будет вызван «<code>__exit__()</code>» . Таким образом, если ошибка происходит в течение назначения списку целей, то на этом этапе она уже́ будет воспринята как ошибка внутри блока «<code>with</code>» . Смотрите шаг 5 ниже.
Исполняется блок кода.
Вызывается метод «<code>__exit__()</code>» менеджера контекста. Если какое-либо исключение приводит к выходу из блока, то тип, значение и стек вызовов этого исключения передаются в качестве аргументов в «<code>__exit__()</code>» – иначе передаются три аргумента «<code>None</code>» .
Если выход из блока был из-за исключения, и возвращённое методом «<code>__exit__()</code>» значение было “ложь” , то это исключение перевызывается. Если же возвращённое значение было “истина” , то это исключение отменяется, и исполнение продолжается с инструкции следующей за блоком инструкции «<code>with</code>» .
Если выход из блока был по любой другой причине, то возвращённое методом «<code>__exit__()</code>» значение игнорируется, и исполнение продолжается обычным образом.
Если у «<code>with</code>» более одного элемента, то это обрабатывается как если бы соответствующие блоки находились один внутри другого :
<code>with A() as a, B() as b:
suite</code>
является эквивалентом
<code>with A() as a:
with B() as b:
suite</code>
Изменилось в версии 3.1 : поддержка множественных выражений контекста.
Смотрите также
PEP 0343 – Инструкция «<code>with</code>»
Спецификация, объяснения и примеры по Питоновской инструкции «<code>with</code>» .
7.6. Задание функций
Код, задающий функцию, создаёт объект пользовательской функции (смотри́те раздел “Иерархия стандартных типов” ) :
<code>funcdef ::= [decorators] "def" funcname "(" [parameter_list] ")" ["->" expression] ":" suite
decorators ::= decorator+
decorator ::= "@" dotted_name ["(" [argument_list [","]] ")"] NEWLINE
dotted_name ::= identifier ("." identifier)*
parameter_list ::= (defparameter ",")*
( "*" [parameter] ("," defparameter)*
[, "**" parameter]
| "**" parameter
| defparameter [","] )
parameter ::= identifier [":" expression]
defparameter ::= parameter ["=" expression]
funcname ::= identifier</code>
Код, задающий функцию, является исполнимой инструкцией. Его исполнение связывает заданное имя в текущей локальной области имён с объектом функции (в котором содержится исполнимый код функции) . Этот объект функции содержит ссылку на текущую глобальную область имён, и она будет использоваться в качестве глобальной во время вызова этой функции.
Код, задающий функцию, не исполняет тело этой функции – оно будет исполняться, когда функция будет вызвана.
Запись текстовой константы, идущая как первая инструкция внутри тела функции, преобразуется в атрибут «<code>__doc__</code>» этой функции и таким образом становится текстом документации этой функции.
Код, задающий функцию, может подвергаться действию одного или нескольких выражений “декораторов” . “Декоратор” исполняется после того, как соответствующая функция уже́ определена, в той же области видимости, в которой содержится код, задающий эту функцию. Результат исполнения выражения “декоратора” должен быть вызываемым объектом, который вызывается, с данной функцией в качестве единственного аргумента. Возвращаемый объект назначается имени данной функции вместо прежнего объекта-функции. Множественные “декораторы” применяются поочерёдно, в порядке близости к функции (в стиле вложенности) . Например, следующий код
<code>@f1(arg)
@f2
def func(): pass</code>
является эквивалентом
<code>def func(): pass
func = f1(arg)(f2(func))</code>
Функция хранит значения по-умолчанию для тех параметров, которые имеют форму <code>parameter = expression</code> . Для таких параметров при вызове функции соответствующее им значение может быть пропущено – в этом случае будет подставлено значение по-умолчанию этого параметра. Если некоторый параметр в описании указан со значением по-умолчанию, то все остальные параметры до «<code>*</code>» обязаны тоже иметь значение по-умолчанию.
Значения параметров по-умолчанию вычисляются, когда исполняется определение функции. Это означает, что выражение вычисляется один раз, когда функция определяется, и одно и то же “предварительно вычисленное” значение используется для каждого вызова. Это особенно важно понять, когда параметр по-умолчанию является изменяемым объектом (например списком или словарём) : если функция изменяет этот объект (например, путем добавления элемента в список) , то это значение по-умолчанию останется изменённым. Как правило, это не то, что было задумано. Способом обойти это является использование «<code>None</code>» в качестве значения по-умолчанию, и явная проверка этого параметра в теле функции, например:
<code>def whats_on_the_telly(penguin=None):
if penguin is None:
penguin = []
penguin.append("property of the zoo")
return penguin</code>
Семантика вызова функции описана более подробно в разделе «calls» . Вызов функции всегда присваивает значения всем параметрам, упомянутым в списке параметров в определении, либо от переданных позиционных аргументов, либо от переданных именованных аргументов, либо от значений по умолчанию. Если присутствует форма “*identifier” , то она инициализируется кортежем, содержащим все лишние позиционные параметры, а при отсутствии таковых – пустым кортежем. Если присутствует форма “**identifier” , то она инициализируется новый словарём, содержащим все лишние именованные аргументы, а при отсутствии таковых – новым пустым словарём. Параметры после “*” или “*identifier” могут быть только именованными параметрами и могут быть переданы только через именованные параметры.
Параметры могут иметь описания в форме “: expression” после имени параметра. Любой параметр может иметь описание, даже те, которые в форме “*identifier” или “**identifier” . Функции могут иметь описание возвращаемого результата в форме “-> expression” в позиции после списка параметров. Эти описания могут быть любыми допустимыми выражениями Питона, они вычисляются при исполнении определения функции. Описания могут быть вычислены в другом порядке, чем они появляются в исходном коде. Наличие описаний не меняет семантику функции. Значения описаний доступны в виде значений словаря в атрибуте «__annotations__» данной функции, с именем нужного параметра в качестве ключа.
Кроме того, можно создавать анонимные функции (функции, не связанные с именем), для непосредственного использования по месту создания внутри выражения. Для этого используются лямбда-формы – это практически синоним понятия “упрощенное определение функции” – их описание в разделе Лямбды. Функцию, определенную инструкцией «<code>def</code>» можно передавать или назначать другому имени так же, как и функцию, определенную лямбда-формой. Форма «<code>def</code>» вообще-то имеет больше возможностей, например, позволяет выполнять несколько инструкций и иметь описания.
Замечание: Функции являются объектами первого класса. Форма «<code>def</code>» выполняемая внутри определения другой функции – создаёт локальную функцию, которая может быть внешнею функцией возвращена в качестве результата или передана куда-либо. Свободные имена, используемые во вложенной функции, могут указывать на локальные переменные внешней функции. Смотрите детали в разделе “Naming and binding”.
Создание классов
“Определение” класса создаёт объект-класс (смотрите раздел “The standard type hierarchy” ) :
<code>classdef ::= [decorators] "class" classname [inheritance] ":" suite
inheritance ::= "(" [argument_list [","] | comprehension] ")"
classname ::= identifier</code>
Код, задающий класс (“определение” класса) , является исполнимой инструкцией. Сначала, если имеется, вычисляется список наследуемых базовых классов (смотри́те подробности в “Customizing class creation” ) . Каждый элемент в этом списке должен давать в результате объект-класс, такой, который допускает создание производного класса. Классы без списка базовых классов – по-умолчанию наследуются от базового объекта:
<code>class Foo:
pass</code>
является эквивалентом
<code>class Foo(object):
pass</code>
Затем основной класс исполняется в новом кадре исполнения (смотри́те раздел “Naming and binding” ) с использованием новосозданной локальной области имён и исходной глобальной области имён. (Обычно код класса содержит только “определения” функций. ) Текстовый объект, идущий с первой строки содержания кода класса, преобразуется в элемент с именем “__doc__” в данной локальной области и, таким образом становится “документацией” этого класса. [4] Когда код класса завершён, его кадр исполнения удаляется, а его локальная область имён сохраняется. Затем создаётся объект-класс с использованием списка наследования для базовых классов, а полученная ранее область имён становится словарём атрибутов класса. Затем полученный объект-класс назначается указанному имени в исходной области имён.
[4] Текстовый объект, идущий с первой строки содержания кода класса, преобразуется в элемент с именем “__doc__” в данной локальной области и, таким образом становится “документацией” этого класса.
Создание классов может быть глубоко настроено с помощью метаклассов.
Классы могут быть “декорированы” , таким же образом как и функции:
<code>@f1(arg)
@f2
class Foo: pass</code>
является эквивалентом
<code>class Foo: pass
Foo = f1(arg)(f2(Foo))</code>
**Замечание:** Переменные, созданные в “определении” класса становятся атрибутами класса, общими для всех его экземпляров. Атрибуты экземпляра могут быть созданы из какого-либо метода посредством «self.name = значение» . Атрибуты и класса и экземпляра доступны через формулировку «self.name» , и при таком способе доступа атрибут экземпляра перекрывает атрибут класса с тем же именем. Атрибуты класса могут использоваться как значения по умолчанию для атрибутов экземпляра, но если эти атрибуты класса являются изменяемыми – то это может привести к неожиданным результатам. Для создания у экземпляра переменных с нестандартными деталями реализации – можно использовать дескрипторы.
Смотрите тпкже
PEP 3129 - “Декораторы” классов
“Определение” класса (так же как и функции) , может подвергаться действию одного или нескольких выражений “декораторов” . Правила исполнения “декораторов” такие же, как и для функций. Результат исполнения выражения “декоратора” должен быть объектом-классом, который затем назначается имени данного класса вместо прежнего класса.
(Все сноски подставлены в соответствующие места. )
Внимание! Этот перевод, возможно, ещё не готов.
Его статус: перевод редактируется
Переведено на Нотабеноиде
http://notabenoid.org/book/5672/17133
Переводчики: Hittih, RedFox
Настройки
Готово:
