8. 複合ステートメント—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.10/reference/compound stmts
移動先:案内検索

8.8。 複合ステートメント

複合ステートメントには、他のステートメント(のグループ)が含まれます。 それらは、何らかの方法でそれらの他のステートメントの実行に影響を与えるか、または制御します。 一般に、複合ステートメントは複数の行にまたがりますが、単純な化身では、複合ステートメント全体が1行に含まれる場合があります。

ifwhile 、および for ステートメントは、従来の制御フロー構造を実装します。 try は、ステートメントのグループの例外ハンドラーやクリーンアップコードを指定し、 with ステートメントは、コードブロックの周囲で初期化および終了コードを実行できます。 関数とクラスの定義も構文的に複合ステートメントです。

複合ステートメントは、1つ以上の「句」で構成されます。 句は、ヘッダーと「スイート」で構成されます。 特定の複合ステートメントの句ヘッダーはすべて同じインデントレベルにあります。 各句ヘッダーは、一意に識別するキーワードで始まり、コロンで終わります。 スイートは、句によって制御されるステートメントのグループです。 スイートは、ヘッダーのコロンに続く、ヘッダーと同じ行にある1つ以上のセミコロンで区切られた単純なステートメントにすることも、後続の行にある1つ以上のインデントされたステートメントにすることもできます。 ネストされた複合ステートメントを含めることができるのは、後者の形式のスイートのみです。 以下は違法です。これは主に、後続の else 句がどの if 句に属するかが明確でないためです。

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
                   | match_stmt
                   | funcdef
                   | classdef
                   | async_with_stmt
                   | async_for_stmt
                   | async_funcdef
 スイート         ::=  stmt_list NEWLINE | NEWLINE INDENT statement+ DEDENT
 ステートメント     ::=  stmt_list NEWLINE | compound_stmt
  stmt_list     ::=  simple_stmt (";" simple_stmt)* [";"]

ステートメントは常にNEWLINEで終わり、その後にDEDENTが続く可能性があることに注意してください。 また、オプションの継続句は常にステートメントを開始できないキーワードで始まるため、あいまいさはありません(Pythonでは、ネストされた if ステートメントを要求することで「ぶら下がり else 」の問題が解決されます)インデントされます)。

次のセクションの文法規則のフォーマットでは、わかりやすくするために各句を別々の行に配置しています。

8.1。 NSif 声明

if ステートメントは、条件付き実行に使用されます。

  if_stmt ::=  "if" assignment_expression ":" suite
             ("elif" assignment_expression ":" suite)*
             ["else" ":" suite]

1つがtrueであることが判明するまで、式を1つずつ評価することにより、スイートの1つを正確に選択します(trueとfalseの定義については、セクションブール演算を参照してください)。 次に、そのスイートが実行されます( if ステートメントの他の部分は実行または評価されません)。 すべての式がfalseの場合、 else 句のスイートが存在する場合は実行されます。


8.2。 NSwhile 声明

while ステートメントは、式が真である限り、繰り返し実行するために使用されます。

  while_stmt ::=  "while" assignment_expression ":" suite
                ["else" ":" suite]

これは式を繰り返しテストし、それがtrueの場合、最初のスイートを実行します。 式がfalseの場合(初めてテストされる場合があります)、else句のスイートが存在する場合は実行され、ループが終了します。

最初のスイートで実行された break ステートメントは、else句のスイートを実行せずにループを終了します。 最初のスイートで実行された continue ステートメントは、スイートの残りの部分をスキップして、式のテストに戻ります。


8.3。 NSfor 声明

for ステートメントは、シーケンスの要素(文字列、タプル、リストなど)またはその他の反復可能なオブジェクトを反復処理するために使用されます。

  for_stmt ::=  "for" target_list "in" expression_list ":" suite
              ["else" ":" suite]

式リストは1回評価されます。 反復可能なオブジェクトを生成する必要があります。 expression_listの結果に対してイテレータが作成されます。 次に、スイートは、イテレータによって提供されたアイテムごとに、イテレータによって返された順序で1回実行されます。 次に、各アイテムは、割り当ての標準ルールを使用してターゲットリストに割り当てられ(割り当てステートメントを参照)、スイートが実行されます。 アイテムが使い果たされると(シーケンスが空になるか、イテレータが StopIteration 例外を発生させるとすぐに)、else句のスイートが実行され、ループが発生します。終了します。

最初のスイートで実行された 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

ターゲットリスト内の名前は、ループの終了時に削除されませんが、シーケンスが空の場合、ループによってまったく割り当てられていません。 ヒント:組み込み関数 range()は、Pascalのfor i := a to b doの効果をエミュレートするのに適した整数のイテレーターを返します。 たとえば、list(range(3))はリスト[0, 1, 2]を返します。

ノート

シーケンスがループによって変更されている場合は微妙です(これは、可変シーケンスでのみ発生する可能性があります。 リスト)。 内部カウンターは、次に使用されるアイテムを追跡するために使用され、これは反復ごとに増分されます。 このカウンターがシーケンスの長さに達すると、ループは終了します。 これは、スイートがシーケンスから現在の(または前の)アイテムを削除した場合、次のアイテムはスキップされることを意味します(すでに処理された現在のアイテムのインデックスを取得するため)。 同様に、スイートが現在のアイテムの前にシーケンス内のアイテムを挿入した場合、現在のアイテムは次回ループを介して再度処理されます。 これは厄介なバグにつながる可能性があり、シーケンス全体のスライスを使用して一時的なコピーを作成することで回避できます。

for x in a[:]:
    if x < 0: a.remove(x)

8.4。 NStry 声明

try ステートメントは、ステートメントのグループの例外ハンドラーやクリーンアップコードを指定します。

  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

exception 句は、1つ以上の例外ハンドラーを指定します。 try 句で例外が発生しない場合、例外ハンドラーは実行されません。 tryスイートで例外が発生すると、例外ハンドラーの検索が開始されます。 この検索では、例外に一致するものが見つかるまで、except句が順番に検査されます。 式のないexcept句が存在する場合は、最後にする必要があります。 すべての例外に一致します。 式を含むexcept句の場合、その式が評価され、結果のオブジェクトが例外と「互換性がある」場合、句は例外と一致します。 オブジェクトが例外オブジェクトのクラスまたは基本クラスである場合、あるいは例外オブジェクトのクラスまたは基本クラスである項目を含むタプルである場合、そのオブジェクトは例外と互換性があります。

例外に一致するexcept句がない場合、例外ハンドラーの検索は、周囲のコードと呼び出しスタックで続行されます。 1

例外句のヘッダーにある式の評価で例外が発生した場合、ハンドラーの元の検索はキャンセルされ、周囲のコードと呼び出しスタックで新しい例外の検索が開始されます(全体として扱われます)。 try ステートメントで例外が発生しました)。

一致するexcept句が見つかると、そのexcept句のasキーワードの後に指定されたターゲットに例外が割り当てられ、存在する場合は、except句のスイートが実行されます。 句を除くすべての句には、実行可能ブロックが必要です。 このブロックの終わりに達すると、tryステートメント全体の後で通常どおり実行が続行されます。 (これは、同じ例外に対して2つのネストされたハンドラーが存在し、例外が内部ハンドラーのtry句で発生した場合、外部ハンドラーは例外を処理しないことを意味します。)

as targetを使用して例外が割り当てられた場合、例外句の最後で例外がクリアされます。 これはまるで

except E as N:
    foo

に翻訳されました

except E as N:
    try:
        foo
    finally:
        del N

つまり、except句の後で例外を参照できるようにするには、例外を別の名前に割り当てる必要があります。 例外は、トレースバックがアタッチされた状態でスタックフレームとの参照サイクルを形成し、次のガベージコレクションが発生するまでそのフレーム内のすべてのローカルを存続させるためにクリアされます。

例外句のスイートが実行される前に、例外に関する詳細が sys モジュールに格納され、 sys.exc_info()を介してアクセスできます。 sys.exc_info()は、例外クラス、例外インスタンス、およびプログラム内のポイントを識別するトレースバックオブジェクト(セクション標準タイプ階層を参照)で構成される3タプルを返します。例外が発生しました。 sys.exc_info()を介してアクセスされた例外に関する詳細は、例外ハンドラーを離れると、以前の値に復元されます。

>>> print(sys.exc_info())
(None, None, None)
>>> try:
...     raise TypeError
... except:
...     print(sys.exc_info())
...     try:
...          raise ValueError
...     except:
...         print(sys.exc_info())
...     print(sys.exc_info())
...
(<class 'TypeError'>, TypeError(), <traceback object at 0x10efad080>)
(<class 'ValueError'>, ValueError(), <traceback object at 0x10efad040>)
(<class 'TypeError'>, TypeError(), <traceback object at 0x10efad080>)
>>> print(sys.exc_info())
(None, None, None)

オプションのelse句は、制御フローが try スイートを離れ、例外が発生せず、 returnContinue 、または break ステートメントが実行されました。 else句の例外は、先行する exception 句では処理されません。

最終的にが存在する場合は、「クリーンアップ」ハンドラーを指定します。 try 句が実行されます。これには、句とelse句を除くすべてのが含まれます。 いずれかの句で例外が発生し、処理されない場合、例外は一時的に保存されます。 finally句が実行されます。 保存された例外がある場合は、finally句の最後で再発生します。 finally句で別の例外が発生した場合、保存された例外が新しい例外のコンテキストとして設定されます。 finally句が returnbreak または continue ステートメントを実行すると、保存された例外は破棄されます。

>>> def f():
...     try:
...         1/0
...     finally:
...         return 42
...
>>> f()
42

finally 句の実行中は、プログラムは例外情報を利用できません。

returnbreak または continue ステートメントが、tryfinallyステートメント、 finally 句も「途中で」実行されます。

関数の戻り値は、最後に実行された return ステートメントによって決定されます。 finally 句は常に実行されるため、finally句で実行されるreturnステートメントは常に最後に実行されます。

>>> def foo():
...     try:
...         return 'try'
...     finally:
...         return 'finally'
...
>>> foo()
'finally'

例外に関する追加情報はセクション Exceptions にあり、 raise ステートメントを使用して例外を生成する方法に関する情報はセクション raiseステートメントにあります。

バージョン3.8で変更: Python 3.8より前は、実装に問題があるため、 continue ステートメントは finally 句で不正でした。


8.5。 NSwith 声明

with ステートメントは、コンテキストマネージャーによって定義されたメソッドでブロックの実行をラップするために使用されます(セクション Withステートメントコンテキストマネージャーを参照)。 これにより、一般的な tryexceptfinally の使用パターンをカプセル化して、再利用しやすくなります。

  with_stmt          ::=  "with" ( "(" with_stmt_contents ","? ")" | with_stmt_contents ) ":" suite
  with_stmt_contents ::=  with_item ("," with_item)*
  with_item          ::=  expression ["as" target]

1つの「アイテム」を含む with ステートメントの実行は、次のように進行します。

  1. コンテキスト式(with_itemで指定された式)が評価され、コンテキストマネージャーが取得されます。

  2. コンテキストマネージャの__enter__()は、後で使用するためにロードされます。

  3. コンテキストマネージャの__exit__()は、後で使用するためにロードされます。

  4. コンテキストマネージャの__enter__()メソッドが呼び出されます。

  5. with ステートメントにターゲットが含まれている場合、__enter__()からの戻り値がターゲットに割り当てられます。

    ノート

    with ステートメントは、__enter__()メソッドがエラーなしで返される場合、__exit__()が常に呼び出されることを保証します。 したがって、ターゲットリストへの割り当て中にエラーが発生した場合、スイート内で発生したエラーと同じように扱われます。 以下のステップ6を参照してください。

  6. スイートが実行されます。

  7. コンテキストマネージャの__exit__()メソッドが呼び出されます。 例外によってスイートが終了した場合、そのタイプ、値、およびトレースバックが引数として__exit__()に渡されます。 それ以外の場合は、3つの None 引数が指定されます。

    例外が原因でスイートが終了し、__exit__()メソッドからの戻り値がfalseの場合、例外が再発生します。 戻り値がtrueの場合、例外は抑制され、 with ステートメントに続くステートメントから実行が続行されます。

    例外以外の理由でスイートが終了した場合、__exit__()からの戻り値は無視され、実行は、実行された種類の終了の通常の場所で続行されます。

次のコード:

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

項目が括弧で囲まれている場合は、複数項目のコンテキストマネージャーを複数行で記述することもできます。 例えば:

with (
    A() as a,
    B() as b,
):
    SUITE

バージョン3.1で変更:複数のコンテキスト式のサポート。


バージョン3.10で変更:グループ化括弧を使用してステートメントを複数行に分割するためのサポート。


も参照してください

PEP 343 -「with」ステートメント
Python with ステートメントの仕様、背景、および例。


8.6。 NSmatch 声明

バージョン3.10の新機能。


matchステートメントは、パターンマッチングに使用されます。 構文:

  match_stmt   ::=  'match' subject_expr ":" NEWLINE INDENT case_block+ DEDENT
  subject_expr ::=  star_named_expression "," star_named_expressions?
                  | named_expression
  case_block   ::=  'case' patterns [guard] ":" block

ノート

このセクションでは、一重引用符を使用してソフトキーワードを示します。


パターンマッチングは、入力(caseに続く)およびサブジェクト値(matchに続く)としてパターンを取ります。 パターン(サブパターンを含む場合があります)は、サブジェクト値と照合されます。 結果は次のとおりです。

  • 一致の成功または失敗(パターンの成功または失敗とも呼ばれます)。
  • 一致した値が名前にバインドされる可能性があります。 このための前提条件については、以下でさらに説明します。

matchおよびcaseキーワードは、ソフトキーワードです。

も参照してください

  • PEP 634 –構造パターンマッチング:仕様
  • PEP 636 –構造パターンマッチング:チュートリアル


8.6.1。 概要

一致ステートメントの論理フローの概要は次のとおりです。

  1. サブジェクト式subject_exprが評価され、結果のサブジェクト値が取得されます。 サブジェクト式にコンマが含まれている場合、タプルは標準ルールを使用して作成されます。

  2. case_blockの各パターンは、サブジェクト値と一致しようとします。 成功または失敗の具体的なルールを以下に説明します。 一致の試行では、パターン内のスタンドアロン名の一部またはすべてをバインドすることもできます。 正確なパターンバインディングルールはパターンタイプごとに異なり、以下に指定されています。 成功したパターンマッチ中に作成された名前バインディングは、実行されたブロックよりも長く存続し、matchステートメントの後に使用できます。

    ノート

    パターンの一致に失敗すると、一部のサブパターンが成功する場合があります。 失敗した一致に対して作成されたバインディングに依存しないでください。 逆に、一致に失敗した後も変数が変更されないままであることに依存しないでください。 正確な動作は実装によって異なり、異なる場合があります。 これは、さまざまな実装で最適化を追加できるようにするために行われた意図的な決定です。

  3. パターンが成功すると、対応するガード(存在する場合)が評価されます。 この場合、すべての名前バインディングが発生したことが保証されます。

    • ガードが真または欠落していると評価された場合、case_block内のblockが実行されます。

    • それ以外の場合は、上記のように次のcase_blockが試行されます。

    • それ以上caseブロックがない場合は、matchステートメントが完了します。

ノート

通常、ユーザーは評価対象のパターンに依存しないでください。 実装に応じて、インタプリタは値をキャッシュするか、繰り返しの評価をスキップする他の最適化を使用する場合があります。


一致ステートメントのサンプル:

>>> flag = False
>>> match (100, 200):
...    case (100, 300):  # Mismatch: 200 != 300
...        print('Case 1')
...    case (100, 200) if flag:  # Successful match, but guard fails
...        print('Case 2')
...    case (100, y):  # Matches and binds y to 200
...        print(f'Case 3, y: {y}')
...    case _:  # Pattern not attempted
...        print('Case 4, I match anything!')
...
Case 3, y: 200

この場合、if flagはガードです。 詳細については、次のセクションをご覧ください。


8.6.2。 警備員

 ガード ::=  "if" named_expression

guardcaseの一部)は、caseブロック内のコードを実行するために成功する必要があります。 if の後に式が続きます。

caseブロックとguardの論理フローは次のとおりです。

  1. caseブロックのパターンが成功したことを確認してください。 パターンが失敗した場合、guardは評価されず、次のcaseブロックがチェックされます。
  2. パターンが成功した場合は、guardを評価します。
    • guard条件がtrueと評価された場合、ケースブロックが選択されます。
    • guard条件がfalseと評価された場合、ケースブロックは選択されていません。
    • guardが評価中に例外を発生させると、例外が発生します。

警備員は表現であるため、副作用を起こすことが許されています。 ガードの評価は、最初のケースブロックから最後のケースブロックまで、一度に1つずつ続行する必要があり、パターンがすべて成功しないケースブロックはスキップします。 (つまり、ガード評価は順番に行われる必要があります。)ケースブロックが選択されると、ガード評価は停止する必要があります。


8.6.3。 反駁できないケースブロック

反駁できないケースブロックは、すべて一致するケースブロックです。 一致ステートメントには、最大で1つの反駁できないケースブロックが含まれる場合があり、最後である必要があります。

ケースブロックは、ガードがなく、そのパターンが反駁できない場合、反駁できないと見なされます。 パターンは、その構文だけで常に成功することを証明できれば、反駁できないと見なされます。 次のパターンのみが反駁できません。


8.6.4。 パターン

ノート

このセクションでは、標準のEBNFを超える文法表記を使用します。

  • SEP.RULE+という表記はRULE (SEP RULE)*の省略形です。
  • 表記!RULEは、否定的な先読みアサーションの省略形です。


patternsの最上位構文は次のとおりです。

 パターン       ::=  open_sequence_pattern | pattern
 パターン        ::=  as_pattern | or_pattern
  closed_pattern ::=  | literal_pattern
                    | capture_pattern
                    | wildcard_pattern
                    | value_pattern
                    | group_pattern
                    | sequence_pattern
                    | mapping_pattern
                    | class_pattern

以下の説明には、説明の目的でパターンが何をするかについての「簡単な用語での」説明が含まれます(ほとんどの説明に影響を与えたドキュメントのRaymond Hettingerへのクレジット)。 これらの説明は純粋に説明を目的としたものであり、は基礎となる実装を反映していない可能性があることに注意してください。 さらに、それらはすべての有効なフォームを網羅しているわけではありません。

8.6.4.1。 またはパターン

ORパターンは、縦棒|で区切られた2つ以上のパターンです。 構文:

  or_pattern ::=  "|".closed_pattern+

最終的なサブパターンのみが反駁できないである可能性があり、あいまいさを避けるために、各サブパターンは同じ名前のセットをバインドする必要があります。

ORパターンは、成功するまで、そのサブパターンのそれぞれをサブジェクト値に順番に一致させます。 その後、ORパターンは成功したと見なされます。 それ以外の場合、どのサブパターンも成功しないと、ORパターンは失敗します。

簡単に言うと、P1 | P2 | ...P1と一致しようとし、失敗した場合はP2と一致しようとし、成功した場合はすぐに成功し、そうでない場合は失敗します。


8.6.4.2。 ASパターン

ASパターンは、 as キーワードの左側にあるORパターンをサブジェクトと照合します。 構文:

  as_pattern ::=  or_pattern "as" capture_pattern

ORパターンが失敗すると、ASパターンも失敗します。 それ以外の場合、ASパターンはサブジェクトをasキーワードの右側の名前にバインドし、成功します。 capture_pattern_にすることはできません。

簡単に言うと、P as NAMEPと一致し、成功するとNAME = <subject>に設定されます。


8.6.4.3。 リテラルパターン

リテラルパターンは、Pythonのほとんどのリテラルに対応します。 構文:

  literal_pattern ::=  signed_number
                     | signed_number "+" NUMBER
                     | signed_number "-" NUMBER
                     | strings
                     | "None"
                     | "True"
                     | "False"
                     | signed_number: NUMBER | "-" NUMBER

ルールstringsとトークンNUMBERは、標準のPython文法で定義されています。 三重引用符で囲まれた文字列がサポートされています。 生の文字列とバイト文字列がサポートされています。 フォーマットされた文字列リテラルはサポートされていません。

signed_number '+' NUMBERおよびsigned_number '-' NUMBERの形式は、複素数を表すためのものです。 左側に実数、右側に虚数が必要です。 例えば 3 + 4j

簡単に言うと、LITERALは、<subject> == LITERALの場合にのみ成功します。 シングルトンNoneTrue、およびFalseの場合、 is 演算子が使用されます。


8.6.4.4。 キャプチャパターン

キャプチャパターンは、サブジェクト値を名前にバインドします。 構文:

  capture_pattern ::=  !'_' NAME

単一の下線_はキャプチャパターンではありません(これは!'_'が表すものです)。 代わりに、wildcard_patternとして扱われます。

特定のパターンでは、特定の名前は1回だけバインドできます。 例えば case x, x: ...は無効ですが、case [x] | x: ...は許可されています。

キャプチャパターンは常に成功します。 バインディングは、 PEP 572 の代入式演算子によって確立されたスコープ規則に従います。 該当するグローバルまたは非ローカルステートメントがない限り、名前は最も近い包含関数スコープのローカル変数になります。

簡単に言うと、NAMEは常に成功し、NAME = <subject>を設定します。


8.6.4.5。 ワイルドカードパターン

ワイルドカードパターンは常に成功し(何にでも一致し)、名前をバインドしません。 構文:

  wildcard_pattern ::=  '_'

_は、任意のパターン内のソフトキーワードですが、パターン内のみです。 これは、matchサブジェクト式、guard、およびcaseブロック内でも、通常どおり識別子です。

簡単に言えば、_は常に成功します。


8.6.4.6。 価値パターン

値パターンは、Pythonで名前付きの値を表します。 構文:

  value_pattern ::=  attr
  attr          ::=  name_or_attr "." NAME
  name_or_attr  ::=  attr | NAME

パターン内の点線の名前は、標準のPython 名前解決ルールを使用して検索されます。 見つかった値がサブジェクト値と等しい場合(==等式演算子を使用)、パターンは成功します。

簡単に言うと、NAME1.NAME2は、<subject> == NAME1.NAME2の場合にのみ成功します。

ノート

同じmatchステートメントで同じ値が複数回発生する場合、インタープリターは最初に見つかった値をキャッシュして、同じルックアップを繰り返すのではなく、それを再利用する場合があります。 このキャッシュは、特定のmatchステートメントの特定の実行に厳密に関連付けられています。


8.6.4.7。 グループパターン

グループパターンを使用すると、ユーザーはパターンの前後に括弧を追加して、目的のグループ化を強調できます。 それ以外の場合、追加の構文はありません。 構文:

  group_pattern ::=  "(" pattern ")"

簡単に言うと、(P)Pと同じ効果があります。


8.6.4.8。 シーケンスパターン

シーケンスパターンには、シーケンス要素と照合するいくつかのサブパターンが含まれています。 構文は、リストまたはタプルの解凍に似ています。

  sequence_pattern       ::=  "[" [maybe_sequence_pattern] "]"
                            | "(" [open_sequence_pattern] ")"
  open_sequence_pattern  ::=  maybe_star_pattern "," [maybe_sequence_pattern]
  maybe_sequence_pattern ::=  ",".maybe_star_pattern+ ","?
  maybe_star_pattern     ::=  star_pattern | pattern
  star_pattern           ::=  "*" (capture_pattern | wildcard_pattern)

シーケンスパターンに括弧または角括弧を使用しても違いはありません(つまり、 (...)[...])。

ノート

末尾のコンマなしで括弧で囲まれた単一のパターン(例: (3 | 4))はグループパターンです。 角括弧で囲まれた単一のパターン(例: [3 | 4])はまだシーケンスパターンです。


最大で1つの星のサブパターンがシーケンスパターンになります。 星のサブパターンは、どの位置でも発生する可能性があります。 星のサブパターンが存在しない場合、シーケンスパターンは固定長のシーケンスパターンです。 それ以外の場合は、可変長のシーケンスパターンです。

以下は、シーケンスパターンをサブジェクト値と照合するための論理フローです。

  1. サブジェクト値がシーケンス 2 でない場合、シーケンスパターンは失敗します。

  2. サブジェクト値がstrbytes、またはbytearrayのインスタンスである場合、シーケンスパターンは失敗します。

  3. 以降の手順は、シーケンスパターンが固定か可変長かによって異なります。

    シーケンスパターンが固定長の場合:

    1. サブジェクトシーケンスの長さがサブパターンの数と等しくない場合、シーケンスパターンは失敗します

    2. シーケンスパターンのサブパターンは、サブジェクトシーケンスの対応するアイテムと左から右に一致します。 サブパターンが失敗するとすぐにマッチングが停止します。 すべてのサブパターンが対応するアイテムの一致に成功した場合、シーケンスパターンは成功します。

    それ以外の場合、シーケンスパターンが可変長の場合:

    1. サブジェクトシーケンスの長さがスター以外のサブパターンの数より短い場合、シーケンスパターンは失敗します。

    2. 主要な非スターサブパターンは、固定長シーケンスの場合と同様に、対応するアイテムと照合されます。

    3. 前のステップが成功した場合、スターサブパターンは、スターサブパターンに続く非スターサブパターンに対応する残りのアイテムを除いて、残りのサブジェクトアイテムで形成されたリストと一致します。

    4. 残りのスター以外のサブパターンは、固定長のシーケンスの場合と同様に、対応するサブジェクトアイテムと照合されます。

    ノート

    サブジェクトシーケンスの長さは、 len()を介して取得されます(つまり、 __len__()プロトコル経由)。 この長さは、値パターンと同様の方法でインタプリタによってキャッシュされます。

簡単に言うと、[P1, P2, P3,, P<N>]は、次のすべてが発生した場合にのみ一致します。

  • <subject>がシーケンスであることを確認してください
  • len(subject) == <N>
  • P1<subject>[0]と一致します(この一致は名前をバインドすることもできることに注意してください)
  • P2<subject>[1]と一致します(この一致は名前をバインドすることもできることに注意してください)
  • 対応するパターン/要素については…など。


8.6.4.9。 マッピングパターン

マッピングパターンには、1つ以上のKey-Valueパターンが含まれています。 構文は辞書の作成に似ています。 構文:

  mapping_pattern     ::=  "{" [items_pattern] "}"
  items_pattern       ::=  ",".key_value_pattern+ ","?
  key_value_pattern   ::=  (literal_pattern | value_pattern) ":" pattern
                         | double_star_pattern
  double_star_pattern ::=  "**" capture_pattern

最大で1つの二重星パターンがマッピングパターンに含まれる場合があります。 二重星パターンは、マッピングパターンの最後のサブパターンである必要があります。

マッピングパターンでの重複キーは許可されていません。 リテラルキーが重複すると、 SyntaxError が発生します。 それ以外の点で同じ値を持つ2つのキーは、実行時に ValueError を発生させます。

以下は、マッピングパターンをサブジェクト値と照合するための論理フローです。

  1. サブジェクト値がマッピング 3 でない場合、マッピングパターンは失敗します。
  2. マッピングパターンで指定されたすべてのキーがサブジェクトマッピングに存在し、各キーのパターンがサブジェクトマッピングの対応するアイテムと一致する場合、マッピングパターンは成功します。
  3. マッピングパターンで重複キーが検出された場合、そのパターンは無効と見なされます。 SyntaxError は、リテラル値が重複している場合に発生します。 または、同じ値の名前付きキーの場合は ValueError

ノート

キーと値のペアは、マッピングサブジェクトのget()メソッドの2つの引数形式を使用して照合されます。 一致するキーと値のペアは、マッピングにすでに存在している必要があり、__missing__()または__getitem__()を介してオンザフライで作成されてはなりません。


簡単に言うと、{KEY1: P1, KEY2: P2, ... }は、次のすべてが発生した場合にのみ一致します。

  • <subject>がマッピングであることを確認してください
  • KEY1 in <subject>
  • P1<subject>[KEY1]と一致します
  • …など、対応するKEY /パターンのペアについても同様です。


8.6.4.10。 クラスパターン

クラスパターンは、クラスとその位置引数およびキーワード引数(存在する場合)を表します。 構文:

  class_pattern       ::=  name_or_attr "(" [pattern_arguments ","?] ")"
  pattern_arguments   ::=  positional_patterns ["," keyword_patterns]
                         | keyword_patterns
  positional_patterns ::=  ",".pattern+
  keyword_patterns    ::=  ",".keyword_pattern+
  keyword_pattern     ::=  NAME "=" pattern

同じキーワードをクラスパターンで繰り返さないでください。

以下は、クラスパターンをサブジェクト値と照合するための論理フローです。

  1. name_or_attrが組み込みの type のインスタンスでない場合は、 TypeError を発生させます。

  2. サブジェクト値がname_or_attrのインスタンスではない場合( isinstance()を介してテスト)、クラスパターンは失敗します。

  3. パターン引数が存在しない場合、パターンは成功します。 それ以外の場合、後続の手順は、キーワードまたは位置引数パターンが存在するかどうかによって異なります。

    いくつかの組み込み型(以下に指定)の場合、サブジェクト全体に一致する単一の位置サブパターンが受け入れられます。 これらのタイプのキーワードパターンは、他のタイプと同様に機能します。

    キーワードパターンのみが存在する場合、それらは次のように1つずつ処理されます。

    1. キーワードは、件名の属性として検索されます。

      • これにより AttributeError 以外の例外が発生した場合、例外が発生します。

      • これにより AttributeError が発生する場合、クラスパターンは失敗しています。

      • それ以外の場合、キーワードパターンに関連付けられたサブパターンは、サブジェクトの属性値と照合されます。 これが失敗すると、クラスパターンは失敗します。 これが成功すると、一致は次のキーワードに進みます。

    2. すべてのキーワードパターンが成功すると、クラスパターンも成功します。

    位置パターンが存在する場合、一致する前に、クラスname_or_attr__ match_args __ 属性を使用してキーワードパターンに変換されます。

    1. getattr(cls, "__match_args__", ())に相当するものが呼び出されます。

      • これにより例外が発生すると、例外が発生します。

      • 戻り値がタプルでない場合、変換は失敗し、 TypeError が発生します。

      • len(cls.__match_args__)よりも多くの位置パターンがある場合、 TypeError が発生します。

      • それ以外の場合、位置パターンiは、__match_args__[i]をキーワードとしてキーワードパターンに変換されます。 __match_args__[i]は文字列である必要があります。 そうでない場合、 TypeError が発生します。

      • 重複するキーワードがある場合、 TypeError が発生します。

    2. すべての位置パターンがキーワードパターンに変換されると、キーワードパターンのみが存在するかのように一致が進行します。

    次の組み込みタイプでは、位置サブパターンの処理が異なります。

    これらのクラスは単一の位置引数を受け入れ、そこでのパターンは属性ではなくオブジェクト全体と照合されます。 たとえば、int(0|1)は値0と一致しますが、値0.0またはFalseとは一致しません。

簡単に言うと、CLS(P1, attr=P2)は、次の場合にのみ一致します。

  • isinstance(<subject>, CLS)
  • CLS.__match_args__を使用して、P1をキーワードパターンに変換します
  • *; キーワード引数ごとにattr=P2
    *;* hasattr(<subject>, "attr")
    • P2<subject>.attrと一致します
  • 対応するキーワード引数/パターンのペアについては…など。

も参照してください

  • PEP 634 –構造パターンマッチング:仕様
  • PEP 636 –構造パターンマッチング:チュートリアル


8.7。 関数の定義

関数定義は、ユーザー定義の関数オブジェクトを定義します(セクション標準型階層を参照)。

  funcdef                   ::=  [decorators] "def" funcname "(" [parameter_list] ")"
                               ["->" expression] ":" suite
 デコレータ                ::=  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 [","]
 パラメーター                 ::=  identifier [":" expression]
  defparameter              ::=  parameter ["=" expression]
  funcname                  ::=  identifier

関数定義は実行可能ステートメントです。 その実行により、現在のローカル名前空間の関数名が関数オブジェクト(関数の実行可能コードのラッパー)にバインドされます。 この関数オブジェクトには、関数が呼び出されたときに使用されるグローバル名前空間として、現在のグローバル名前空間への参照が含まれています。

関数定義は関数本体を実行しません。 これは、関数が呼び出されたときにのみ実行されます。 4

関数定義は、1つ以上のデコレータ式でラップできます。 デコレータ式は、関数が定義されたときに、関数定義を含むスコープで評価されます。 結果は、関数オブジェクトを唯一の引数として呼び出される呼び出し可能である必要があります。 戻り値は、関数オブジェクトではなく関数名にバインドされます。 複数のデコレータがネストされた方法で適用されます。 たとえば、次のコード

@f1(arg)
@f2
def func(): pass

とほぼ同等です

def func(): pass
func = f1(arg)(f2(func))

ただし、元の関数は一時的にfuncという名前にバインドされていません。

バージョン3.9で変更:関数は有効なassignment_expressionで装飾できます。 以前は、文法ははるかに制限的でした。 詳細については、 PEP 614 を参照してください。


1つ以上のパラメータパラメータ = の形式である場合、関数は「デフォルトのパラメータ値」を持っていると言われます。 デフォルト値のパラメーターの場合、対応する引数を呼び出しから省略できます。その場合、パラメーターのデフォルト値が置き換えられます。 パラメータにデフォルト値がある場合、「*」までの後続のすべてのパラメータにもデフォルト値が必要です。これは、文法で表現されていない構文上の制限です。

デフォルトのパラメーター値は、関数定義の実行時に左から右に評価されます。これは、関数が定義されたときに式が1回評価され、同じ「事前計算」値がに使用されることを意味します。各呼び出し。 これは、デフォルトのパラメータ値がリストや辞書などの可変オブジェクトである場合を理解するために特に重要です。関数がオブジェクトを変更する場合(例: リストに項目を追加することにより)、デフォルトのパラメータ値が事実上変更されます。 これは一般的に意図されたものではありません。 これを回避する方法は、デフォルトとしてNoneを使用し、関数の本体で明示的にテストすることです。例:

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 を参照してください。


パラメータには、パラメータ名の後に「: expression」の形式の注釈が付いている場合があります。 *identifierまたは**identifierの形式の場合でも、任意のパラメーターに注釈を付けることができます。 関数には、パラメータリストの後に「-> expression」という形式の「return」注釈が付いている場合があります。 これらのアノテーションは、任意の有効なPython式にすることができます。 アノテーションが存在しても、関数のセマンティクスは変更されません。 注釈値は、関数オブジェクトの__annotations__属性のパラメーター名でキー設定されたディクショナリの値として使用できます。 __ future __ からのannotationsインポートを使用すると、注釈は実行時に文字列として保持されるため、評価を延期できます。 それ以外の場合は、関数定義の実行時に評価されます。 この場合、注釈はソースコードに表示される順序とは異なる順序で評価される可能性があります。

式ですぐに使用できるように、無名関数(名前にバインドされていない関数)を作成することもできます。 これは、セクション Lambdas で説明されているラムダ式を使用します。 ラムダ式は単純化された関数定義の省略形にすぎないことに注意してください。 「 def 」ステートメントで定義された関数は、ラムダ式で定義された関数と同じように、受け渡したり、別の名前に割り当てたりすることができます。 「def」フォームは、複数のステートメントと注釈を実行できるため、実際にはより強力です。

プログラマーのメモ:関数はファーストクラスのオブジェクトです。 関数定義内で実行される「def」ステートメントは、返されるか、渡されることができるローカル関数を定義します。 ネストされた関数で使用される自由変数は、defを含む関数のローカル変数にアクセスできます。 詳細については、セクション命名とバインディングを参照してください。

も参照してください

PEP 3107 -関数の注釈
関数アノテーションの元の仕様。
PEP 484 -タイプのヒント
注釈の標準的な意味の定義:タイプヒント。
PEP 526 -変数注釈の構文
クラス変数やインスタンス変数を含むヒント変数宣言を入力する機能
PEP 563 -注釈の評価の延期
熱心な評価の代わりに実行時に文字列形式で注釈を保持することにより、注釈内の前方参照をサポートします。


8.8。 クラス定義

クラス定義はクラスオブジェクトを定義します(セクション標準タイプ階層を参照):

  classdef    ::=  [decorators] "class" classname [inheritance] ":" suite
 継承 ::=  "(" [argument_list] ")"
 クラス名   ::=  identifier

クラス定義は実行可能なステートメントです。 継承リストは通常、基本クラスのリストを提供します(より高度な使用法については、メタクラスを参照)。したがって、リスト内の各項目は、サブクラス化を許可するクラスオブジェクトに評価される必要があります。 継承リストのないクラスは、デフォルトで、基本クラス object から継承します。 したがって、

class Foo:
    pass

と同等です

class Foo(object):
    pass

次に、クラスのスイートは、新しく作成されたローカル名前空間と元のグローバル名前空間を使用して、新しい実行フレームで実行されます(名前空間とバインディングを参照)。 (通常、スイートには主に関数定義が含まれています。)クラスのスイートが実行を終了すると、その実行フレームは破棄されますが、ローカル名前空間は保存されます。 5 次に、基本クラスの継承リストと属性ディクショナリの保存されたローカル名前空間を使用して、クラスオブジェクトが作成されます。 クラス名は、元のローカル名前空間のこのクラスオブジェクトにバインドされます。

クラス本体で属性が定義される順序は、新しいクラスの__dict__で保持されます。 これは、クラスが作成された直後、および定義構文を使用して定義されたクラスに対してのみ信頼できることに注意してください。

クラスの作成は、 metaclasses を使用して大幅にカスタマイズできます。

クラスも装飾できます。関数を装飾するときと同じように、

@f1(arg)
@f2
class Foo: pass

とほぼ同等です

class Foo: pass
Foo = f1(arg)(f2(Foo))

デコレータ式の評価ルールは、関数デコレータの場合と同じです。 結果はクラス名にバインドされます。

バージョン3.9で変更:クラスは任意の有効なassignment_expressionで装飾できます。 以前は、文法ははるかに制限的でした。 詳細については、 PEP 614 を参照してください。


プログラマーのメモ:クラス定義で定義されている変数はクラス属性です。 それらはインスタンスによって共有されます。 インスタンス属性は、self.name = valueのメソッドで設定できます。 クラス属性とインスタンス属性はどちらも「self.name」という表記でアクセスできます。インスタンス属性は、この方法でアクセスすると、同じ名前のクラス属性を非表示にします。 クラス属性はインスタンス属性のデフォルトとして使用できますが、可変値を使用すると予期しない結果が生じる可能性があります。 記述子を使用して、実装の詳細が異なるインスタンス変数を作成できます。

も参照してください

PEP 3115 -Python3000のメタクラス
メタクラスの宣言を現在の構文に変更した提案、およびメタクラスを持つクラスの構築方法のセマンティクス。
PEP 3129 -クラスデコレータ
クラスデコレータを追加した提案。 関数とメソッドのデコレータは、 PEP 318 で導入されました。


8.9。 コルーチン

バージョン3.5の新機能。


8.9.1。 コルーチン関数の定義

  async_funcdef ::=  [decorators] "async" "def" funcname "(" [parameter_list] ")"
                   ["->" expression] ":" suite

Pythonコルーチンの実行は、多くの時点で一時停止および再開できます(コルーチンを参照)。 await 式、 async for 、および async with は、コルーチン関数の本体でのみ使用できます。

async def構文で定義された関数は、awaitまたはasyncキーワードが含まれていない場合でも、常にコルーチン関数です。

コルーチン関数の本体内でyield from式を使用するのは SyntaxError です。

コルーチン関数の例:

async def func(param1, param2):
    do_stuff()
    await some_coroutine()

バージョン3.7で変更: awaitおよびasyncがキーワードになりました。 以前は、コルーチン関数の体内でのみそのように扱われていました。


8.9.2。 NSasync for 声明

  async_for_stmt ::=  "async" for_stmt

非同期イテレータは、非同期イテレータを直接返す__aiter__メソッドを提供します。このメソッドは、__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

詳細については、__aiter__()および__anext__()も参照してください。

コルーチン関数の本体の外でasync forステートメントを使用するのは SyntaxError です。


8.9.3。 NSasync with 声明

  async_with_stmt ::=  "async" with_stmt

非同期コンテキストマネージャーは、 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)

詳細については、__aenter__()および__aexit__()も参照してください。

コルーチン関数の本体の外でasync withステートメントを使用するのは SyntaxError です。

も参照してください

PEP 492 -非同期および待機構文のコルーチン
コルーチンをPythonの適切なスタンドアロンの概念にし、サポートする構文を追加した提案。


脚注

1

別の例外を発生させる finally 句がない限り、例外は呼び出しスタックに伝播されます。 その新しい例外により、古い例外が失われます。

2

パターンマッチングでは、シーケンスは次のいずれかとして定義されます。


次の標準ライブラリクラスはシーケンスです。

ノート

タイプstrbytes、およびbytearrayのサブジェクト値がシーケンスパターンと一致しません。

3

パターンマッチングでは、マッピングは次のいずれかとして定義されます。


標準ライブラリクラス dict および types.MappingProxyType はマッピングです。

4

関数本体の最初のステートメントとして表示される文字列リテラルは、関数の__doc__属性に変換されるため、関数の docstring に変換されます。

5

クラス本体の最初のステートメントとして表示される文字列リテラルは、名前空間の__doc__アイテムに変換されるため、クラスの docstring に変換されます。