8. Складені висловлювання¶
Складені висловлювання містять (групи) інші висловлювання; вони певним чином впливають або контролюють виконання цих інших операторів. Загалом складені висловлювання охоплюють кілька рядків, хоча в простих варіантах ціле складене висловлювання може міститися в одному рядку.
Оператори 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
|async_with_stmt
|async_for_stmt
|async_funcdef
suite ::=stmt_list
NEWLINE | NEWLINE INDENTstatement
+ DEDENT statement ::=stmt_list
NEWLINE |compound_stmt
stmt_list ::=simple_stmt
(";"simple_stmt
)* [";"]
Зауважте, що оператори завжди закінчуються на NEWLINE
, після якого, можливо, йде DEDENT
. Також зауважте, що необов’язкові речення продовження завжди починаються з ключового слова, яке не може розпочинати оператор, тому немає ніяких двозначностей (проблему «висячих else
» вирішено в Python, вимагаючи вкладених операторів if
з відступом).
Форматування правил граматики в наступних розділах розміщує кожне речення в окремому рядку для ясності.
8.1. Оператор if
¶
Оператор if
використовується для умовного виконання:
if_stmt ::= "if"assignment_expression
":"suite
("elif"assignment_expression
":"suite
)* ["else" ":"suite
]
Він вибирає точно один із наборів, обчислюючи вирази один за іншим, доки один не буде визнаний істинним (див. розділ Логічні операції для визначення істинного та хибного); тоді цей набір виконується (і жодна інша частина оператора if
не виконується і не оцінюється). Якщо всі вирази хибні, виконується набір пропозиції else
, якщо вона є.
8.2. Оператор while
¶
Інструкція while
використовується для повторного виконання, доки вираз є істинним:
while_stmt ::= "while"assignment_expression
":"suite
["else" ":"suite
]
Це багаторазово перевіряє вираз і, якщо воно вірне, виконує перший набір; якщо вираз є хибним (що може бути першим, коли його перевіряють), набір пропозиції else
виконується, і цикл припиняється.
Інструкція break
, виконана в першому наборі, завершує цикл без виконання набору речень else
. Інструкція continue
, виконана в першому наборі, пропускає решту пакета і повертається до перевірки виразу.
8.3. Оператор for
¶
Оператор for
використовується для повторення елементів послідовності (таких як рядок, кортеж або список) або іншого ітерованого об’єкта:
for_stmt ::= "for"target_list
"in"expression_list
":"suite
["else" ":"suite
]
The expression list is evaluated once; it should yield an iterable object. An
iterator is created for the result of the expression_list
. The suite is
then executed once for each item provided by the iterator, in the order returned
by the iterator. Each item in turn is assigned to the target list using the
standard rules for assignments (see Заяви про призначення), and then the suite is
executed. When the items are exhausted (which is immediately when the sequence
is empty or an iterator raises a StopIteration
exception), the suite in
the else
clause, if present, is executed, and the loop terminates.
Інструкція break
, виконана в першому наборі, завершує цикл без виконання набору речень else
. Інструкція continue
, виконана в першому наборі, пропускає решту набору і продовжує з наступним елементом або з пропозицією else
, якщо наступного елемента немає.
Цикл for виконує призначення змінним у цільовому списку. Це перезаписує всі попередні призначення цим змінним, включаючи ті, що зроблені в наборі циклу for:
for i in range(10):
print(i)
i = 5 # this will not affect the for-loop
# because i will be overwritten with the next
# index in the range
Names in the target list are not deleted when the loop is finished, but if the
sequence is empty, they will not have been assigned to at all by the loop. Hint:
the built-in function range()
returns an iterator of integers suitable to
emulate the effect of Pascal’s for i := a to b do
; e.g., list(range(3))
returns the list [0, 1, 2]
.
Примітка
There is a subtlety when the sequence is being modified by the loop (this can only occur for mutable sequences, e.g. lists). An internal counter is used to keep track of which item is used next, and this is incremented on each iteration. When this counter has reached the length of the sequence the loop terminates. This means that if the suite deletes the current (or a previous) item from the sequence, the next item will be skipped (since it gets the index of the current item which has already been treated). Likewise, if the suite inserts an item in the sequence before the current item, the current item will be treated again the next time through the loop. This can lead to nasty bugs that can be avoided by making a temporary copy using a slice of the whole sequence, e.g.,
for x in a[:]:
if x < 0: a.remove(x)
8.4. Оператор try
¶
The try
statement specifies exception handlers and/or cleanup code
for a group of statements:
try_stmt ::=try1_stmt
|try2_stmt
try1_stmt ::= "try" ":"suite
("except" [expression
["as"identifier
]] ":"suite
)+ ["else" ":"suite
] ["finally" ":"suite
] try2_stmt ::= "try" ":"suite
"finally" ":"suite
The except
clause(s) specify one or more exception handlers. When no
exception occurs in the try
clause, no exception handler is executed.
When an exception occurs in the try
suite, a search for an exception
handler is started. This search inspects the except clauses in turn until one
is found that matches the exception. An expression-less except clause, if
present, must be last; it matches any exception. For an except clause with an
expression, that expression is evaluated, and the clause matches the exception
if the resulting object is «compatible» with the exception. An object is
compatible with an exception if the object is the class or a
non-virtual base class of the exception object,
or a tuple containing an item that is the class or a non-virtual base class
of the exception object.
If no except clause matches the exception, the search for an exception handler continues in the surrounding code and on the invocation stack. 1
If the evaluation of an expression in the header of an except clause raises an
exception, the original search for a handler is canceled and a search starts for
the new exception in the surrounding code and on the call stack (it is treated
as if the entire try
statement raised the exception).
When a matching except clause is found, the exception is assigned to the target
specified after the as
keyword in that except clause, if present, and
the except clause’s suite is executed. All except clauses must have an
executable block. When the end of this block is reached, execution continues
normally after the entire try statement. (This means that if two nested
handlers exist for the same exception, and the exception occurs in the try
clause of the inner handler, the outer handler will not handle the exception.)
When an exception has been assigned using as target
, it is cleared at the
end of the except clause. This is as if
except E as N:
foo
було перекладено на:
except E as N:
try:
foo
finally:
del N
This means the exception must be assigned to a different name to be able to refer to it after the except clause. Exceptions are cleared because with the traceback attached to them, they form a reference cycle with the stack frame, keeping all locals in that frame alive until the next garbage collection occurs.
Before an except clause’s suite is executed, details about the exception are
stored in the sys
module and can be accessed via sys.exc_info()
.
sys.exc_info()
returns a 3-tuple consisting of the exception class, the
exception instance and a traceback object (see section Стандартна ієрархія типів) identifying
the point in the program where the exception occurred. sys.exc_info()
values are restored to their previous values (before the call) when returning
from a function that handled an exception.
Необов’язкова пропозиція else
виконується, якщо потік керування виходить із набору try
, не було викликано винятків і немає return
, continue
або Інструкція break
була виконана. Винятки в пункті else
не обробляються попередніми пунктами except
.
If finally
is present, it specifies a „cleanup“ handler. The
try
clause is executed, including any except
and
else
clauses. If an exception occurs in any of the clauses and is
not handled, the exception is temporarily saved. The finally
clause
is executed. If there is a saved exception it is re-raised at the end of the
finally
clause. If the finally
clause raises another
exception, the saved exception is set as the context of the new exception.
If the finally
clause executes a return
, break
or continue
statement, the saved exception is discarded:
>>> def f():
... try:
... 1/0
... finally:
... return 42
...
>>> f()
42
The exception information is not available to the program during execution of
the finally
clause.
When a return
, break
or continue
statement is
executed in the try
suite of a try
…finally
statement, the finally
clause is also executed „on the way out.“
The return value of a function is determined by the last return
statement executed. Since the finally
clause always executes, a
return
statement executed in the finally
clause will
always be the last one executed:
>>> def foo():
... try:
... return 'try'
... finally:
... return 'finally'
...
>>> foo()
'finally'
Додаткову інформацію про винятки можна знайти в розділі Винятки, а інформацію про використання оператора raise
для створення винятків можна знайти в розділі Оператор raise.
8.5. Оператор with
¶
Оператор with
використовується для обгортання виконання блоку методами, визначеними контекстним менеджером (див. розділ З менеджерами контексту операторів). Це дозволяє інкапсулювати загальні try
…except
…finally
моделі використання для зручного повторного використання.
with_stmt ::= "with"with_item
(","with_item
)* ":"suite
with_item ::=expression
["as"target
]
Виконання оператора with
з одним «елементом» відбувається наступним чином:
The context expression (the expression given in the
with_item
) is evaluated to obtain a context manager.The context manager’s
__enter__()
is loaded for later use.The context manager’s
__exit__()
is loaded for later use.The context manager’s
__enter__()
method is invoked.If a target was included in the
with
statement, the return value from__enter__()
is assigned to it.Примітка
The
with
statement guarantees that if the__enter__()
method returns without an error, then__exit__()
will always be called. Thus, if an error occurs during the assignment to the target list, it will be treated the same as an error occurring within the suite would be. See step 6 below.Сюїта виконана.
The context manager’s
__exit__()
method is invoked. If an exception caused the suite to be exited, its type, value, and traceback are passed as arguments to__exit__()
. Otherwise, threeNone
arguments are supplied.If the suite was exited due to an exception, and the return value from the
__exit__()
method was false, the exception is reraised. If the return value was true, the exception is suppressed, and execution continues with the statement following thewith
statement.If the suite was exited for any reason other than an exception, the return value from
__exit__()
is ignored, and execution proceeds at the normal location for the kind of exit that was taken.
Наступний код:
with EXPRESSION as TARGET:
SUITE
семантично еквівалентний:
manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not exit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
exit(manager, None, None, None)
З більш ніж одним елементом менеджери контексту обробляються так, ніби кілька операторів with
були вкладеними:
with A() as a, B() as b:
SUITE
семантично еквівалентний:
with A() as a:
with B() as b:
SUITE
Змінено в версії 3.1: Підтримка кількох контекстних виразів.
8.6. Визначення функцій¶
Визначення функції визначає об’єкт функції, визначений користувачем (див. розділ Стандартна ієрархія типів):
funcdef ::= [decorators
] "def"funcname
"(" [parameter_list
] ")" ["->"expression
] ":"suite
decorators ::=decorator
+ decorator ::= "@"assignment_expression
NEWLINE parameter_list ::=defparameter
(","defparameter
)* "," "/" ["," [parameter_list_no_posonly
]] |parameter_list_no_posonly
parameter_list_no_posonly ::=defparameter
(","defparameter
)* ["," [parameter_list_starargs
]] |parameter_list_starargs
parameter_list_starargs ::= "*" [parameter
] (","defparameter
)* ["," ["**"parameter
[","]]] | "**"parameter
[","] parameter ::=identifier
[":"expression
] defparameter ::=parameter
["="expression
] funcname ::=identifier
Визначення функції - це виконуваний оператор. Його виконання прив’язує назву функції в поточному локальному просторі імен до об’єкта функції (обгортка навколо виконуваного коду для функції). Цей об’єкт функції містить посилання на поточний глобальний простір імен як глобальний простір імен, який буде використано під час виклику функції.
Визначення функції не виконує тіло функції; це виконується лише під час виклику функції. 2
Визначення функції може бути обгорнуте одним або кількома виразами decorator. Вирази декоратора обчислюються, коли функція визначена в області видимості, яка містить визначення функції. Результат має бути викликаним, який викликається з об’єктом функції як єдиним аргументом. Повернене значення прив’язується до імені функції замість об’єкта функції. Кілька декораторів застосовуються вкладеним способом. Наприклад, такий код:
@f1(arg)
@f2
def func(): pass
приблизно еквівалентно
def func(): pass
func = f1(arg)(f2(func))
за винятком того, що вихідна функція тимчасово не прив’язана до імені func
.
Змінено в версії 3.9: Functions may be decorated with any valid assignment_expression
.
Previously, the grammar was much more restrictive; see PEP 614 for
details.
Коли один або більше параметрів мають форму параметр =
вираз, кажуть, що функція має «значення параметрів за замовчуванням». Для параметра зі значенням за замовчуванням відповідний argument може бути пропущений у виклику, у цьому випадку значення параметра за замовчуванням замінюється. Якщо параметр має значення за замовчуванням, усі наступні параметри до «*
» також повинні мати значення за замовчуванням — це синтаксичне обмеження, яке не виражається граматикою.
Default parameter values are evaluated from left to right when the function
definition is executed. This means that the expression is evaluated once, when
the function is defined, and that the same «pre-computed» value is used for each
call. This is especially important to understand when a default parameter is a
mutable object, such as a list or a dictionary: if the function modifies the
object (e.g. by appending an item to a list), the default value is in effect
modified. This is generally not what was intended. A way around this is to use
None
as the default, and explicitly test for it in the body of the function,
e.g.:
def whats_on_the_telly(penguin=None):
if penguin is None:
penguin = []
penguin.append("property of the zoo")
return penguin
Більш детально семантика виклику функції описана в розділі Дзвінки. Виклик функції завжди призначає значення всім параметрам, згаданим у списку параметрів, або з позиційних аргументів, з ключових аргументів, або зі значень за замовчуванням. Якщо присутня форма «*identifier
», вона ініціалізується кортежем, що отримує будь-які надлишкові позиційні параметри, за умовчанням порожній кортеж. Якщо присутня форма «*identifier
», вона ініціалізується новим упорядкованим відображенням, отримуючи будь-які надлишкові аргументи ключового слова, за умовчанням до нового порожнього відображення того самого типу. Параметри після «*
» або «*identifier
» є параметрами лише для ключових слів і можуть передаватися лише аргументами ключових слів. Параметри перед «/
» є лише позиційними параметрами і можуть передаватися лише позиційними аргументами.
Змінено в версії 3.8: Синтаксис параметра функції /
може використовуватися для позначення лише позиційних параметрів. Подробиці див. PEP 570.
Параметри можуть мати анотацію у формі «:вираз
» після імені параметра. Будь-який параметр може мати анотацію, навіть у формі *ідентифікатор
або **ідентифікатор
. Функції можуть мати анотацію «повернення» у формі «-> вираз
» після списку параметрів. Ці анотації можуть бути будь-яким дійсним виразом Python. Наявність анотацій не змінює семантику функції. Значення анотацій доступні як значення словника, ключ якого містить імена параметрів в атрибуті __annotations__
об’єкта функції. Якщо використовується імпорт анотацій
із __future__
, анотації зберігаються як рядки під час виконання, що дає змогу відкласти оцінку. В іншому випадку вони оцінюються під час виконання визначення функції. У цьому випадку анотації можуть оцінюватися в іншому порядку, ніж у вихідному коді.
Також можна створювати анонімні функції (функції, не прив’язані до імені) для негайного використання у виразах. Тут використовуються лямбда-вирази, описані в розділі Лямбда. Зауважте, що лямбда-вираз — це лише скорочення спрощеного визначення функції; функція, визначена в операторі «def
», може бути передана або присвоєна іншому імені так само, як функція, визначена лямбда-виразом. Форма «def
» насправді є потужнішою, оскільки вона дозволяє виконувати кілька операторів і анотацій.
Примітка програміста: Функції є об’єктами першого класу. Оператор «def
», який виконується всередині визначення функції, визначає локальну функцію, яку можна повертати або передавати. Вільні змінні, які використовуються у вкладеній функції, можуть отримати доступ до локальних змінних функції, що містить def. Перегляньте розділ Називання та зв’язування для деталей.
Дивись також
- PEP 3107 - Анотації функцій
Оригінальна специфікація для анотацій функцій.
- PEP 484 - підказки типу
Визначення стандартного значення для анотацій: тип підказок.
- PEP 526 - Синтаксис для анотацій змінних
Ability to type hint variable declarations, including class variables and instance variables
- PEP 563 - Відкладена оцінка анотацій
Підтримка прямих посилань в анотаціях завдяки збереженню анотацій у формі рядка під час виконання замість нетерплячої оцінки.
8.7. Визначення класів¶
Визначення класу визначає об’єкт класу (див. розділ Стандартна ієрархія типів):
classdef ::= [decorators
] "class"classname
[inheritance
] ":"suite
inheritance ::= "(" [argument_list
] ")" classname ::=identifier
Визначення класу є виконуваним оператором. Список успадкування зазвичай надає список базових класів (див. Метакласи для більш просунутого використання), тому кожен елемент у списку повинен оцінюватися як об’єкт класу, який дозволяє створювати підкласи. Класи без списку успадкування успадковують, за замовчуванням, від базового класу object
; отже,
class Foo:
pass
еквівалентно
class Foo(object):
pass
Потім набір класів виконується в новому фреймі виконання (див. Називання та зв’язування), використовуючи щойно створений локальний простір імен і оригінальний глобальний простір імен. (Зазвичай набір містить в основному визначення функцій.) Коли набір класу завершує виконання, його кадр виконання відкидається, але його локальний простір імен зберігається. 3 Потім створюється об’єкт класу з використанням списку успадкування для базових класів і збереженого локального простору імен для словника атрибутів. Ім’я класу прив’язане до цього об’єкта класу в оригінальному локальному просторі імен.
Порядок, у якому атрибути визначені в тілі класу, зберігається в __dict__
нового класу. Зауважте, що це надійно лише відразу після створення класу та лише для класів, які були визначені за допомогою синтаксису визначення.
Створення класів можна значно налаштувати за допомогою metaclasses.
Класи також можна декорувати: як і при декоруванні функцій,
@f1(arg)
@f2
class Foo: pass
приблизно еквівалентно
class Foo: pass
Foo = f1(arg)(f2(Foo))
Правила оцінки для виразів декоратора такі ж, як і для декораторів функцій. Потім результат прив’язується до імені класу.
Змінено в версії 3.9: Classes may be decorated with any valid assignment_expression
.
Previously, the grammar was much more restrictive; see PEP 614 for
details.
Примітка програміста: Змінні, визначені у визначенні класу, є атрибутами класу; їх ділять інстанції. Атрибути екземпляра можна встановити в методі за допомогою self.name = value
. Як атрибути класу, так і атрибути екземпляра доступні через нотацію «self.name
», а атрибут екземпляра приховує атрибут класу з таким самим іменем, коли до нього звертаються таким чином. Атрибути класу можна використовувати як значення за замовчуванням для атрибутів екземплярів, але використання там змінних значень може призвести до неочікуваних результатів. Дескриптори можна використовувати для створення змінних екземпляра з різними деталями реалізації.
8.8. Співпрограми¶
Нове в версії 3.5.
8.8.1. Визначення функції співпрограми¶
async_funcdef ::= [decorators
] "async" "def"funcname
"(" [parameter_list
] ")" ["->"expression
] ":"suite
Execution of Python coroutines can be suspended and resumed at many points
(see coroutine). Inside the body of a coroutine function, await
and
async
identifiers become reserved keywords; await
expressions,
async for
and async with
can only be used in
coroutine function bodies.
Функції, визначені за допомогою синтаксису async def
, завжди є функціями співпрограми, навіть якщо вони не містять ключових слів await
або async
.
Використання виразу yield from
всередині тіла функції співпрограми є SyntaxError
.
Приклад функції співпрограми:
async def func(param1, param2):
do_stuff()
await some_coroutine()
8.8.2. Оператор async for
¶
async_for_stmt ::= "async" for_stmt
asynchronous iterable надає метод __aiter__
, який безпосередньо повертає asynchronous iterator, який може викликати асинхронний код у своєму методі __anext__
.
Оператор async for
дозволяє зручно виконувати ітерації над асинхронними ітераціями.
Наступний код:
async for TARGET in ITER:
SUITE
else:
SUITE2
Семантично еквівалентний:
iter = (ITER)
iter = type(iter).__aiter__(iter)
running = True
while running:
try:
TARGET = await type(iter).__anext__(iter)
except StopAsyncIteration:
running = False
else:
SUITE
else:
SUITE2
See also __aiter__()
and __anext__()
for details.
Це SyntaxError
, якщо використовувати оператор async for
поза тілом функції співпрограми.
8.8.3. Оператор async with
¶
async_with_stmt ::= "async" with_stmt
Асинхронний менеджер контексту (asynchronous context manager) — це менеджер контексту (context manager),який може призупинити виконання своїх методів enter і exit.
Наступний код:
async with EXPRESSION as TARGET:
SUITE
семантично еквівалентний:
manager = (EXPRESSION)
aenter = type(manager).__aenter__
aexit = type(manager).__aexit__
value = await aenter(manager)
hit_except = False
try:
TARGET = value
SUITE
except:
hit_except = True
if not await aexit(manager, *sys.exc_info()):
raise
finally:
if not hit_except:
await aexit(manager, None, None, None)
See also __aenter__()
and __aexit__()
for details.
Це SyntaxError
, якщо використовувати оператор async with
поза тілом функції співпрограми.
Дивись також
- PEP 492 - Співпрограми з синтаксисом async і await
Пропозиція, яка зробила співпрограми справжньою автономною концепцією в Python і додала допоміжний синтаксис.
Виноски
- 1
Виняток поширюється на стек викликів, якщо немає пункту
finally
, який викликає інший виняток. Цей новий виняток призводить до втрати старого.- 2
A string literal appearing as the first statement in the function body is transformed into the function’s
__doc__
attribute and therefore the function’s docstring.- 3
Рядковий літерал, що з’являється як перший оператор у тілі класу, перетворюється на елемент простору імен
__doc__
і, отже, на docstring класу.