8. 複合文 (compound statement)¶
複合文には、他の文 (のグループ) が入ります; 複合文は、中に入っている他の文の実行の制御に何らかのやり方で影響を及ぼします。一般的には、複合文は複数行にまたがって書かれますが、全部の文を一行に連ねた単純な書き方もあります。
if
、 while
、および for
文は、伝統的な制御フロー構成を実現します。 try
は例外処理および/または一連の文に対するクリーンアップコードを指定します。それに対して、 with
文はコードのかたまりの前後でコードの初期化と終了処理を実行できるようにします。関数とクラス定義もまた、構文的には複合文です。
複合文は、一つ以上の '節 (clause)' からなります。節は、ヘッダと 'スイート (suite)' からなります。一つの複合文を成す各節のヘッダは、全て同じインデントレベルに置かれます。各節のヘッダは一意に識別するキーワードで始まり、コロンで終わります。スイートは、節によって制御される文の集まりです。スイートは、ヘッダがある行のコロンの後にセミコロンで区切って置かれた一つ以上の単純文、または、ヘッダに続く行で一つ多くインデントされた文の集まりです。後者の形式のスイートに限り、さらに複合文をネストできます; 以下の文は、 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
suite ::=stmt_list
NEWLINE | NEWLINE INDENTstatement
+ DEDENT statement ::=stmt_list
NEWLINE |compound_stmt
stmt_list ::=simple_stmt
(";"simple_stmt
)* [";"]
なお、文は常に NEWLINE
か、その後に DEDENT
が続いたもので終了します。また、オプションの継続節は必ず、文を開始できない予約語で始まるので、曖昧さは存在しません。 (Python では、 'ぶら下がり (dangling) else
' 問題は、ネストされた if
文をインデントさせることで解決されます)。
以下の節における文法規則の記述方式は、明確さのために、各節を別々の行に書くようにしています。
8.1. if
文¶
if
文は、条件分岐を実行するために使われます:
if_stmt ::= "if"assignment_expression
":"suite
("elif"assignment_expression
":"suite
)* ["else" ":"suite
]
if
文は、式を一つ一つ評価してゆき、真になるまで続けて、真になった節のスイートだけを選択します (真: true と偽: false の定義については、 ブール演算 (boolean operation) 節を参照してください); 次に、選択したスイートを実行します (そして、 if
文の他の部分は、実行や評価をされません)。全ての式が偽になった場合、 else
節があれば、そのスイートが実行されます。
8.2. while
文¶
while
文は、式の値が真である間、実行を繰り返すために使われます:
while_stmt ::= "while"assignment_expression
":"suite
["else" ":"suite
]
while
文は式を繰り返し真偽評価し、真であれば最初のスイートを実行します。式が偽であれば (最初から偽になっていることもありえます)、 else
節がある場合にはそれを実行し、ループを終了します。
最初のスイート内で break
文が実行されると、 else
節のスイートを実行することなくループを終了します。 continue
文が最初のスイート内で実行されると、スイート内にある残りの文の実行をスキップして、式の真偽評価に戻ります。
8.3. for
文¶
for
文は、シーケンス (文字列、タプルまたはリスト) や、その他の反復可能なオブジェクト (iterable object) 内の要素に渡って反復処理を行うために使われます:
for_stmt ::= "for"target_list
"in"starred_list
":"suite
["else" ":"suite
]
starred_list
式は一度だけ評価され、評価結果として イテラブル オブジェクトを返す必要があります。そのイテラブルから イテレータ が作られます。まず、イテレータから生成される最初の要素が、通常の代入式のルールに従って target_list
に代入され(代入文 (assignment statement) 節参照)、1つ目のスイート (suite) が実行されます。これが、イテレータから生成される各要素に対して繰り返されます。イテレータのすべての要素が処理されたあと、 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()
は、 整数の不変算術列を表します。例えば、 range(3)
を反復すると0、1そして2の順に結果を返します。
バージョン 3.11 で変更: 式のリストの中でアスタリスク付きの式 (starred elements) を指定できるようになりました。
8.4. try
文¶
try
文は、ひとまとめの文に対して、例外処理および/またはクリーンアップコードを指定します:
try_stmt ::=try1_stmt
|try2_stmt
|try3_stmt
try1_stmt ::= "try" ":"suite
("except" [expression
["as"identifier
]] ":"suite
)+ ["else" ":"suite
] ["finally" ":"suite
] try2_stmt ::= "try" ":"suite
("except" "*"expression
["as"identifier
] ":"suite
)+ ["else" ":"suite
] ["finally" ":"suite
] try3_stmt ::= "try" ":"suite
"finally" ":"suite
例外に関するその他の情報は 例外 節にあります。また、 raise
文の使用による例外の生成に関する情報は、 raise 文 節にあります。
8.4.1. except
節¶
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, the
expression must evaluate to an exception type or a tuple of exception types.
The raised exception matches an except
clause whose expression evaluates
to the class or a non-virtual base class of the exception object,
or to a tuple that contains such a class.
例外がどの except
節にも合致しなかった場合、現在のコードを囲うさらに外側、そして呼び出しスタックへと検索を続けます。 [1]
except
節のヘッダにある式を値評価するときに例外が発生すると、元々のハンドラ検索はキャンセルされ、新たな例外に対する例外ハンドラの検索を現在の except
節の外側のコードや呼び出しスタックに対して行います (try
文全体が例外を発行したかのように扱われます)。
対応する except
節が見つかると、except
節のスイートが実行されます。その際、 as
キーワードが except
節に存在すれば、その後で指定されているターゲットに例外が代入されます。全ての except
節は実行可能なブロックを持っていなければなりません。このブロックの末尾に到達すると、通常は try
文全体の直後から実行を継続します。(このことは、ネストされた二つの例外ハンドラが同じ例外に対して存在し、内側のハンドラ内の try
節で例外が発生した場合、外側のハンドラはその例外を処理しないことを意味します。)
例外が as target
を使って代入されたとき、それは except
節の終わりに消去されます。これはちょうど、以下のコード:
except E as N:
foo
が、以下のコードに翻訳されたかのようなものです:
except E as N:
try:
foo
finally:
del N
よって、例外を except
節以降で参照できるようにするためには、別の名前に代入されなければなりません。例外が削除されるのは、トレースバックが付与されると、そのスタックフレームと循環参照を形作り、次のガベージ収集までそのフレーム内のすべての局所変数を生存させてしまうからです。
except
節のスイートが実行される前に、例外が sys
モジュールに格納されます。
except
節の中では、 sys.exception()
を呼び出す事によってこの例外にアクセスすることができます。
例外ハンドラを抜けると、 sys
モジュールに格納されている例外の値が、一つ前の値に戻ります:
>>> print(sys.exception())
None
>>> try:
... raise TypeError
... except:
... print(repr(sys.exception()))
... try:
... raise ValueError
... except:
... print(repr(sys.exception()))
... print(repr(sys.exception()))
...
TypeError()
ValueError()
TypeError()
>>> print(sys.exception())
None
8.4.2. except*
節¶
The except*
clause(s) are used for handling
ExceptionGroup
s. The exception type for matching is interpreted as in
the case of except
, but in the case of exception groups we can have
partial matches when the type matches some of the exceptions in the group.
This means that multiple except*
clauses can execute,
each handling part of the exception group.
Each clause executes at most once and handles an exception group
of all matching exceptions. Each exception in the group is handled by at most
one except*
clause, the first that matches it.
>>> try:
... raise ExceptionGroup("eg",
... [ValueError(1), TypeError(2), OSError(3), OSError(4)])
... except* TypeError as e:
... print(f'caught {type(e)} with nested {e.exceptions}')
... except* OSError as e:
... print(f'caught {type(e)} with nested {e.exceptions}')
...
caught <class 'ExceptionGroup'> with nested (TypeError(2),)
caught <class 'ExceptionGroup'> with nested (OSError(3), OSError(4))
+ Exception Group Traceback (most recent call last):
| File "<stdin>", line 2, in <module>
| ExceptionGroup: eg
+-+---------------- 1 ----------------
| ValueError: 1
+------------------------------------
Any remaining exceptions that were not handled by any except*
clause are re-raised at the end, along with all exceptions that were
raised from within the except*
clauses. If this list contains
more than one exception to reraise, they are combined into an exception
group.
If the raised exception is not an exception group and its type matches
one of the except*
clauses, it is caught and wrapped by an
exception group with an empty message string.
>>> try:
... raise BlockingIOError
... except* BlockingIOError as e:
... print(repr(e))
...
ExceptionGroup('', (BlockingIOError()))
An except*
clause must have a matching expression; it cannot be except*:
.
Furthermore, this expression cannot contain exception group types, because that would
have ambiguous semantics.
It is not possible to mix except
and except*
in the same try
.
break
, continue
and return
cannot appear in an except*
clause.
8.4.3. else
節¶
オプションの else
節は、コントロールフローが try
スイートを抜け、例外が送出されず、 return
文、 continue
文、 break
文のいずれもが実行されなかった場合に実行されます。
else
節で起きた例外は、手前にある except
節では処理されません。
8.4.4. finally
節¶
finally
節がある場合は、 '後始末' の対処を指定します。まず except
節や else
節を含め、 try
節が実行されます。それらの節の中で例外が起き、その例外が処理されていない場合には、例外は一時的に保存されます。次に finally
節が実行されます。保存された例外があった場合は、 finally
節の末尾で再送出されます。 finally
節で別の例外が送出される場合は、保存されていた例外は新しい例外のコンテキストとして設定されます。 finally
節で return
文、 break
文あるいは continue
文を実行した場合は、保存された例外は破棄されます:
>>> def f():
... try:
... 1/0
... finally:
... return 42
...
>>> f()
42
finally
節を実行している間は、プログラムからは例外情報は利用できません。
try
...finally
文の try
スイート内で return
、 break
、または continue
文が実行された場合、 finally
節も、この文を '抜け出る途中に' 実行されます。
関数の返り値は最後に実行された return
文によって決まります。
finally
節は必ず実行されるため、finally
節で実行された return
文は常に最後に実行されることになります:
>>> def foo():
... try:
... return 'try'
... finally:
... return 'finally'
...
>>> foo()
'finally'
バージョン 3.8 で変更: Python3.8 以前では、実装上の問題により finally
節での continue
文は不正でした。
8.5. with
文¶
with
文は、ブロックの実行を、コンテキストマネージャによって定義されたメソッドでラップするために使われます (with文とコンテキストマネージャ セクションを参照してください)。これにより、よくある try
...except
...finally
利用パターンをカプセル化して便利に再利用することができます。
with_stmt ::= "with" ( "("with_stmt_contents
","? ")" |with_stmt_contents
) ":"suite
with_stmt_contents ::=with_item
(","with_item
)* with_item ::=expression
["as"target
]
一つの "要素" を持つ with
文の実行は以下のように進行します:
コンテキスト式 (
with_item
で与えられた式) を評価することで、コンテキストマネージャを取得します。コンテキストマネージャの
__enter__()
メソッドが、後で使うためにロードされます。コンテキストマネージャの
__exit__()
メソッドが、後で使うためにロードされます。コンテキストマネージャの
__enter__()
メソッドが呼ばれます。with
文にターゲットが含まれていたら、それに__enter__()
からの戻り値が代入されます。注釈
with
文は、__enter__()
メソッドがエラーなく終了した場合には__exit__()
が常に呼ばれることを保証します。ですので、もしターゲットリストへの代入中にエラーが発生した場合には、これはそのスイートの中で発生したエラーと同じように扱われます。以下のステップ 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)
try:
TARGET = value
SUITE
except:
if not exit(manager, *sys.exc_info()):
raise
else:
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 で変更: 括弧で囲むことで、文を複数行に分割して書けるようになりました。
8.6. match
文¶
Added in version 3.10.
match 文はパターンマッチングを行う目的で使われます。 構文:
match_stmt ::= 'match'subject_expr
":" NEWLINE INDENTcase_block
+ DEDENT subject_expr ::=star_named_expression
","star_named_expressions
? |named_expression
case_block ::= 'case'patterns
[guard
] ":"block
注釈
このセクションでは、一重引用符で囲まれているものは ソフトキーワード を表します。
パターンマッチングは、パターン (case
の後ろ) とマッチング対象の値 (match
の後ろ)を入力とします。
パターン (サブパターンを含みうる) は、マッチング対象の値に対して、マッチするかどうかの判定が行われます。結果として次のことが起こります:
マッチ成功、もしくはマッチ失敗 (パターン成功・失敗とも呼ばれます)。
マッチした値の名前への束縛。必要な条件は後述します。
match
と case
キーワードは ソフトキーワード です。
8.6.1. 概要¶
match 文の論理的な動作の流れの概要は次の通りです:
サブジェクト式
subject_expr
が評価され、サブジェクト値が得られます。 サブジェクト式がコンマを含む場合、 通常のルール に従ってタプルが作成されます。case_block
内の各パターンに対して、サブジェクト値がマッチするかどうかをチェックします。 マッチ成功・失敗の具体的なルールは後述します。 マッチングのチェックにより、パターン内の名前の一部あるいはすべてに値が束縛されます。 具体的な束縛ルールはパターンの種類によって異なるため、後述します。 マッチが成功したパターンの中で束縛された名前は、そのパターンのブロック内だけでなく、 match 文の後でも使用することができます。注釈
パターンマッチが全体として失敗しても、その中に含まれるサブパターンが成功する可能性があります。 失敗したマッチで発生する名前束縛を前提としたコードを書かないように気をつけてください。 逆に、マッチが失敗したあとで変数の値が変わっていないというのも前提にしないでください。 実際どういう振る舞いになるかは Python の実装依存であり、実装間で異なる可能性があります。 色々な実装が最適化を行えるよう、意図的に実装依存としています。
パターンが成功した場合、該当のガードが (もしあれば) 評価されます。 この場合、パターン内の名前がすべて束縛されていることが保証されています。
ガードの評価値が真であるか、もしくはガードがなければ、
case_block
内のblock
が実行されます。そうでなければ、次の
case_block
に対して再び上記の処理が実行されます。これ以上 case block が存在しない場合は、 match 文が終了します。
注釈
基本的に、 match 文のパターンが評価されるという前提でコードを書くべきではありません。 インタープリタの実装によっては、結果をキャッシュするなどの最適化を行い、評価をスキップする可能性があります。
簡単な 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. ガード¶
guard ::= "if" named_expression
guard
(case
一部として現れる) が成功してはじめて、その case
ブロックのコードが実行されます。
ガードは if
の後に式を書く形で表記されます。
guard
付きの case
ブロックの処理の流れは次のとおりです:
case
ブロックのパターンが成功するかどうかをチェックする。 失敗した場合は、guard
は評価されず、次のcase
ブロックのチェックに進む。パターンが成功した場合は、
guard
の評価が行われます。guard
条件の評価値が真である場合、該当の case ブロックが選択されます。guard
条件の評価値が偽の場合、該当の case ブロックは選択されません。guard
の評価中に例外が送出された場合は、その例外がそのまま送出されます。
ガードは式であるため、副作用を起こすことができます。 ガードの評価は、最初の case ブロックから順に、パターンが失敗した case ブロックは飛ばしつつ、一つづつ評価されなければいけません (つまり、ガードの評価は書かれている順番で実行される必要があります)。 また、case ブロックが選択された時点で、ガードの評価をそれ以上行ってはいけません。
8.6.3. 論駁不可能なケースブロック¶
論駁不可能なケースブロックとは、何にでもマッチするケースブロックのことです。 match 文の中で、論駁不可能なケースブロックは最大一つまで、かつ最後に位置する必要があります。
ケースブロックが論駁不可能であるためには、ガードがなく、パターンが論駁不可能である必要があります。 パターンが論駁不可能であるためには、その文法上の構造のみから、それが常に成功することが証明できる必要があります。 論駁不可能なパターンは以下のようなもののみです:
8.6.4. パターン¶
注釈
このセクションでは、通常のEBNFを拡張した文法記法を使用します。
SEP.RULE+
という表記はRULE (SEP RULE)*
の略です。!RULE
は否定先読みの条件を表します。
patterns
のトップレベルの構文は以下の通りです:
patterns ::=open_sequence_pattern
|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 パターン¶
OR パターンは、縦線 |
で区切られた複数のパターンからなります。
構文:
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 NAME
は P
をマッチさせ、成功した場合に NAME = <subject>
の代入を行います。
8.6.4.3. リテラルパターン¶
リテラルパターンは、一部を除く Python の リテラル に対応します。 構文:
literal_pattern ::=signed_number
|signed_number
"+" NUMBER |signed_number
"-" NUMBER |strings
| "None" | "True" | "False" signed_number ::= ["-"] NUMBER
strings
というルールと NUMBER
というトークンは Python の文法仕様 で定義されています。
クォート3つで囲われた文字列や raw 文字列、 raw バイト列も使用可能です。
f-strings は使用できません。
signed_number '+' NUMBER
と signed_number '-' NUMBER
という構文は 複素数 を表現するためのものです。
そのため、左側には実数、右側には虚数を書く必要があります。
例: 3 + 4j
。
簡単に言うと、 LITERAL
は <subject> == LITERAL
であるときのみ成功するパターンです。
シングルトンである None
と True
、 False
は is
演算子を使って比較されます。
8.6.4.4. キャプチャパターン¶
キャプチャパターンは、サブジェクト値を名前に束縛します。 構文:
capture_pattern ::= !'_' NAME
アンダースコア一文字の _
はキャプチャパターンではありません (!'_'
が表しているのはこの条件です) 。
wildcard_pattern
として扱われます。
パターン一つの中で、一つの名前は一度しか束縛することができません。
例えば、 case x, x: ...
は間違いですが、 case [x] | x: ...
は正しいです。
キャプチャパターンは常に成功します。
束縛された名前のスコープは、 PEP 572 で確立された代入式演算子のスコープルールと同じです。
すなわち、当てはまる global
文 か nonlocal
文がない限り、その局所変数のスコープは、該当の match 文を包む最も内側の関数となります。
簡単に言うと、 NAME
は常に成功し、 NAME = <subject>
の代入が行われます。
8.6.4.5. ワイルドカードパターン¶
ワイルドカードパターンは常に成功 (何に対してもマッチする) し、名前の束縛はしません。 構文:
wildcard_pattern ::= '_'
_
は、パターンの中で使用された場合は常に ソフトキーワード です。
しかし、パターンの中でない場合はソフトキーワードではありません。
たとえサブジェクト式や 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. グループパターン¶
A group pattern allows users to add parentheses around patterns to emphasize the intended grouping. Otherwise, it has no additional syntax. Syntax:
group_pattern ::= "(" pattern
")"
In simple terms (P)
has the same effect as P
.
8.6.4.8. シーケンスパターン¶
A sequence pattern contains several subpatterns to be matched against sequence elements. The syntax is similar to the unpacking of a list or tuple.
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
)
There is no difference if parentheses or square brackets
are used for sequence patterns (i.e. (...)
vs [...]
).
注釈
A single pattern enclosed in parentheses without a trailing comma
(e.g. (3 | 4)
) is a group pattern.
While a single pattern enclosed in square brackets (e.g. [3 | 4]
) is
still a sequence pattern.
At most one star subpattern may be in a sequence pattern. The star subpattern may occur in any position. If no star subpattern is present, the sequence pattern is a fixed-length sequence pattern; otherwise it is a variable-length sequence pattern.
The following is the logical flow for matching a sequence pattern against a subject value:
If the subject value is not a sequence [2], the sequence pattern fails.
If the subject value is an instance of
str
,bytes
orbytearray
the sequence pattern fails.The subsequent steps depend on whether the sequence pattern is fixed or variable-length.
If the sequence pattern is fixed-length:
If the length of the subject sequence is not equal to the number of subpatterns, the sequence pattern fails
Subpatterns in the sequence pattern are matched to their corresponding items in the subject sequence from left to right. Matching stops as soon as a subpattern fails. If all subpatterns succeed in matching their corresponding item, the sequence pattern succeeds.
Otherwise, if the sequence pattern is variable-length:
If the length of the subject sequence is less than the number of non-star subpatterns, the sequence pattern fails.
The leading non-star subpatterns are matched to their corresponding items as for fixed-length sequences.
If the previous step succeeds, the star subpattern matches a list formed of the remaining subject items, excluding the remaining items corresponding to non-star subpatterns following the star subpattern.
Remaining non-star subpatterns are matched to their corresponding subject items, as for a fixed-length sequence.
注釈
The length of the subject sequence is obtained via
len()
(i.e. via the__len__()
protocol). This length may be cached by the interpreter in a similar manner as value patterns.
In simple terms [P1, P2, P3,
... , P<N>]
matches only if all the following
happens:
<subject>
がシーケンスかをチェックするlen(subject) == <N>
P1
matches<subject>[0]
(note that this match can also bind names)P2
matches<subject>[1]
(note that this match can also bind names)... and so on for the corresponding pattern/element.
8.6.4.9. マッピングパターン¶
A mapping pattern contains one or more key-value patterns. The syntax is similar to the construction of a dictionary. Syntax:
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
At most one double star pattern may be in a mapping pattern. The double star pattern must be the last subpattern in the mapping pattern.
Duplicate keys in mapping patterns are disallowed. Duplicate literal keys will
raise a SyntaxError
. Two keys that otherwise have the same value will
raise a ValueError
at runtime.
The following is the logical flow for matching a mapping pattern against a subject value:
If the subject value is not a mapping [3],the mapping pattern fails.
If every key given in the mapping pattern is present in the subject mapping, and the pattern for each key matches the corresponding item of the subject mapping, the mapping pattern succeeds.
If duplicate keys are detected in the mapping pattern, the pattern is considered invalid. A
SyntaxError
is raised for duplicate literal values; or aValueError
for named keys of the same value.
注釈
Key-value pairs are matched using the two-argument form of the mapping
subject's get()
method. Matched key-value pairs must already be present
in the mapping, and not created on-the-fly via __missing__()
or
__getitem__()
.
In simple terms {KEY1: P1, KEY2: P2, ... }
matches only if all the following
happens:
<subject>
がマッピングかをチェックするKEY1 in <subject>
P1
は<subject>[KEY1]
にマッチする... and so on for the corresponding KEY/pattern pair.
8.6.4.10. クラスパターン¶
A class pattern represents a class and its positional and keyword arguments (if any). Syntax:
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
The same keyword should not be repeated in class patterns.
The following is the logical flow for matching a class pattern against a subject value:
If
name_or_attr
is not an instance of the builtintype
, raiseTypeError
.If the subject value is not an instance of
name_or_attr
(tested viaisinstance()
), the class pattern fails.If no pattern arguments are present, the pattern succeeds. Otherwise, the subsequent steps depend on whether keyword or positional argument patterns are present.
For a number of built-in types (specified below), a single positional subpattern is accepted which will match the entire subject; for these types keyword patterns also work as for other types.
If only keyword patterns are present, they are processed as follows, one by one:
I. The keyword is looked up as an attribute on the subject.
If this raises an exception other than
AttributeError
, the exception bubbles up.If this raises
AttributeError
, the class pattern has failed.Else, the subpattern associated with the keyword pattern is matched against the subject's attribute value. If this fails, the class pattern fails; if this succeeds, the match proceeds to the next keyword.
II. If all keyword patterns succeed, the class pattern succeeds.
If any positional patterns are present, they are converted to keyword patterns using the
__match_args__
attribute on the classname_or_attr
before matching:I. The equivalent of
getattr(cls, "__match_args__", ())
is called.If this raises an exception, the exception bubbles up.
If the returned value is not a tuple, the conversion fails and
TypeError
is raised.If there are more positional patterns than
len(cls.__match_args__)
,TypeError
is raised.Otherwise, positional pattern
i
is converted to a keyword pattern using__match_args__[i]
as the keyword.__match_args__[i]
must be a string; if notTypeError
is raised.If there are duplicate keywords,
TypeError
is raised.
- II. Once all positional patterns have been converted to keyword patterns,
the match proceeds as if there were only keyword patterns.
For the following built-in types the handling of positional subpatterns is different:
These classes accept a single positional argument, and the pattern there is matched against the whole object rather than an attribute. For example
int(0|1)
matches the value0
, but not the value0.0
.
In simple terms CLS(P1, attr=P2)
matches only if the following happens:
isinstance(<subject>, CLS)
convert
P1
to a keyword pattern usingCLS.__match_args__
For each keyword argument
attr=P2
:hasattr(<subject>, "attr")
P2
は<subject>.attr
にマッチする
... and so on for the corresponding keyword argument/pattern pair.
8.7. 関数定義¶
関数定義は、ユーザ定義関数オブジェクトを定義します (標準型の階層 節参照):
funcdef ::= [decorators
] "def"funcname
[type_params
] "(" [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 ::= "*" [star_parameter
] (","defparameter
)* ["," ["**"parameter
[","]]] | "**"parameter
[","] parameter ::=identifier
[":"expression
] star_parameter ::=identifier
[":" ["*"]expression
] defparameter ::=parameter
["="expression
] funcname ::=identifier
関数定義は実行可能な文です。関数定義を実行すると、現在のローカルな名前空間内で関数名を関数オブジェクト (関数の実行可能コードをくるむラッパー) に束縛します。この関数オブジェクトには、関数が呼び出された際に使われるグローバルな名前空間として、現在のグローバルな名前空間への参照が入っています。
関数定義は関数本体を実行しません; 関数本体は関数が呼び出された時にのみ実行されます。 [4]
関数定義は一つ以上の デコレータ 式でラップできます。デコレータ式は関数を定義するとき、関数定義の入っているスコープで評価されます。その結果は、関数オブジェクトを唯一の引数にとる呼び出し可能オブジェクトでなければなりません。関数オブジェクトの代わりに、返された値が関数名に束縛されます。複数のデコレータはネストして適用されます。例えば、以下のようなコード:
@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.
A list of type parameters may be given in square brackets
between the function's name and the opening parenthesis for its parameter list.
This indicates to static type checkers that the function is generic. At runtime,
the type parameters can be retrieved from the function's
__type_params__
attribute. See Generic functions for more.
バージョン 3.12 で変更: Type parameter lists are new in Python 3.12.
1 つ以上の 仮引数 が parameter =
expression の形を取っているとき、関数は "デフォルト引数値" を持つと言います。デフォルト値を持つ仮引数では、呼び出し時にそれに対応する 実引数 は省略でき、その場合は仮引数のデフォルト値が使われます。ある引数がデフォルト値を持っている場合、それ以降 "*
" が出てくるまでの引数は全てデフォルト値を持っていなければなりません -- これは文法定義では表現されていない構文的制限です。
デフォルト引数値は関数定義が実行されるときに左から右へ評価されます。 これは、デフォルト引数の式は関数が定義されるときにただ一度だけ評価され、同じ "計算済みの" 値が呼び出しのたびに使用されることを意味します。この仕様を理解しておくことは特に、デフォルト引数値がリストや辞書のようなミュータブルなオブジェクトであるときに重要です: 関数がこのオブジェクトを変更 (例えばリストに要素を追加) すると、このデフォルト引数値が変更の影響を受けてしまします。一般には、これは意図しない動作です。このような動作を避けるには、デフォルト値として None
を使い、この値を関数本体の中で明示的にテストします。例えば以下のようにします:
def whats_on_the_telly(penguin=None):
if penguin is None:
penguin = []
penguin.append("property of the zoo")
return penguin
関数呼び出しの意味付けに関する詳細は、 呼び出し (call) 節で述べられています。
関数呼び出しを行うと、パラメタリストに記述された全てのパラメタに、位置引数、キーワード引数、デフォルト値のいずれかから値が代入されます。
"*identifier
" 形式が存在すれば、余ったすべての位置引数を受け取ったタプルに初期化されます。
このデフォルト値は空のタプルです。
"**identifier
" 形式が存在すれば、余ったすべてのキーワード引数を受け取った順序付きのマッピングオブジェクトに初期化されます。
このデフォルト値は同じ型の空のマッピングオブジェクトです。
"*
" や "*identifier
" の後のパラメタはキーワード専用パラメータで、キーワード引数によってのみ渡されます。
"/
" の前のパラメタは位置専用パラメータで、位置引数によってのみ渡されます。
バージョン 3.8 で変更: The /
function parameter syntax may be used to indicate positional-only
parameters. See PEP 570 for details.
Parameters may have an annotation of the form ": expression
"
following the parameter name. Any parameter may have an annotation, even those of the form
*identifier
or **identifier
. (As a special case, parameters of the form
*identifier
may have an annotation ": *expression
".) Functions may have "return" annotation of
the form "-> expression
" after the parameter list. These annotations can be
any valid Python expression. The presence of annotations does not change the
semantics of a function. The annotation values are available as values of
a dictionary keyed by the parameters' names in the __annotations__
attribute of the function object. If the annotations
import from
__future__
is used, annotations are preserved as strings at runtime which
enables postponed evaluation. Otherwise, they are evaluated when the function
definition is executed. In this case annotations may be evaluated in
a different order than they appear in the source code.
バージョン 3.11 で変更: Parameters of the form "*identifier
" may have an annotation
": *expression
". See PEP 646.
式を即時に使用するために、無名関数 (名前に束縛されていない関数) を作成することもできます。
これは ラムダ (lambda) の節で解説されているラムダ式を使います。
ラムダ式は簡略化された関数定義の簡略表現に過ぎないことに注意してください; "def
" 文で定義された関数もラムダ式で作成された関数のように、引数として渡せたり、他の名前に割り当てることができます。
複数の式とアノテーションが実行できるので、 "def
" 形式の方がより強力です。
プログラマへのメモ: 関数は第一級オブジェクトです。関数定義内で実行された "def
" 文は、返り値や引数として渡せるローカル関数を定義します。ネストした関数内で使われる自由変数は、 def を含んでいる関数のローカル変数にアクセスできます。詳細は 名前づけと束縛 (naming and binding) 節を参照してください。
参考
- PEP 3107 - Function Annotations
関数アノテーションの元の仕様書。
- PEP 484 - 型ヒント
アノテーションの標準的な意味付けである型ヒントの定義。
- PEP 526 - Syntax for Variable Annotations
Ability to type hint variable declarations, including class variables and instance variables.
- PEP 563 - アノテーションの遅延評価
実行時にアノテーションを貪欲評価するのではなく文字列形式で保持することによる、アノテーションにおける前方参照のサポート
- PEP 318 - Decorators for Functions and Methods
Function and method decorators were introduced. Class decorators were introduced in PEP 3129.
8.8. クラス定義¶
クラス定義は、クラスオブジェクトを定義します (標準型の階層 節参照):
classdef ::= [decorators
] "class"classname
[type_params
] [inheritance
] ":"suite
inheritance ::= "(" [argument_list
] ")" classname ::=identifier
クラス定義は実行可能な文です。継承リストは通常、基底クラスリストを与えます (より高度な使い方は、 メタクラス を参照してください)。ですから、リストのそれぞれの要素の評価はサブクラス化しても良いクラスであるべきです。継承リストのないクラスは、デフォルトで、基底クラス object
を継承するので:
class Foo:
pass
は、以下と同等です
class Foo(object):
pass
次にクラスのスイートが、新たな実行フレーム (名前づけと束縛 (naming and binding) を参照してください) 内で、新たに作られたローカル名前空間と元々のグローバル名前空間を使って実行されます (通常、このスイートには主に関数定義が含まれます)。クラスのスイートが実行し終えると、実行フレームは破棄されますが、ローカルな名前空間は保存されます。[5] 次に、継承リストを基底クラスに、保存されたローカル名前空間を属性値辞書に、それぞれ使ってクラスオブジェクトが生成されます。最後に、もとのローカル名前空間において、クラス名がこのクラスオブジェクトに束縛されます。
The order in which attributes are defined in the class body is preserved
in the new class's __dict__
. Note that this is reliable only right
after the class is created and only for classes that were defined using
the definition syntax.
クラス作成は、 メタクラス を利用して大幅にカスタマイズできます。
関数をデコレートするのと同じように、クラスもデコレートすることが出来ます、
@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.
A list of type parameters may be given in square brackets
immediately after the class's name.
This indicates to static type checkers that the class is generic. At runtime,
the type parameters can be retrieved from the class's
__type_params__
attribute. See Generic classes for more.
バージョン 3.12 で変更: Type parameter lists are new in Python 3.12.
プログラマのための注釈: クラス定義内で定義された変数はクラス属性であり、全てのインスタンス間で共有されます。インスタンス属性は、メソッドの中で self.name = value
とすることで設定できます。クラス属性もインスタンス属性も "self.name
" 表記でアクセスでき、この表記でアクセスしたとき、インスタンス属性は同名のクラス属性を隠蔽します。クラス属性は、インスタンス属性のデフォルト値として使えますが、そこにミュータブルな値を使うと予期せぬ結果につながります。 記述子 を使うと、詳細な実装が異なるインスタンス変数を作成できます。
8.9. コルーチン¶
Added in version 3.5.
8.9.1. コルーチン関数定義¶
async_funcdef ::= [decorators
] "async" "def"funcname
"(" [parameter_list
] ")" ["->"expression
] ":"suite
Python で実行しているコルーチンは多くの時点で一時停止と再開ができます (coroutine を参照)。await
式である async for
と async with
はコルーチン関数の本体でしか使えません。
Functions defined with async def
syntax are always coroutine functions,
even if they do not contain await
or async
keywords.
コルーチン関数の本体の中で yield from
式を使用すると SyntaxError
になります。
コルーチン関数の例:
async def func(param1, param2):
do_stuff()
await some_coroutine()
バージョン 3.7 で変更: await
and async
are now keywords; previously they were only
treated as such inside the body of a coroutine function.
8.9.2. async for
文¶
async_for_stmt ::= "async" for_stmt
asynchronous iterable は、その __anext__
メソッドで非同期なコードを実行可能な、asynchronous iterator を直接返す __aiter__
メソッドを提供しています。
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. async with
文¶
async_with_stmt ::= "async" with_stmt
asynchronous context manager は、 enter メソッドと exit メソッド内部で実行を一時停止できる context manager です。
以下のコード:
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 - async 構文および await 構文付きのコルーチン
コルーチンを Python のまともな独り立ちした概念にし、サポートする構文を追加した提案。
8.10. Type parameter lists¶
Added in version 3.12.
バージョン 3.13 で変更: Support for default values was added (see PEP 696).
type_params ::= "["type_param
(","type_param
)* "]" type_param ::=typevar
|typevartuple
|paramspec
typevar ::=identifier
(":"expression
)? ("="expression
)? typevartuple ::= "*"identifier
("="expression
)? paramspec ::= "**"identifier
("="expression
)?
Functions (including coroutines), classes and type aliases may contain a type parameter list:
def max[T](args: list[T]) -> T:
...
async def amax[T](args: list[T]) -> T:
...
class Bag[T]:
def __iter__(self) -> Iterator[T]:
...
def add(self, arg: T) -> None:
...
type ListOrSet[T] = list[T] | set[T]
Semantically, this indicates that the function, class, or type alias is generic over a type variable. This information is primarily used by static type checkers, and at runtime, generic objects behave much like their non-generic counterparts.
Type parameters are declared in square brackets ([]
) immediately
after the name of the function, class, or type alias. The type parameters
are accessible within the scope of the generic object, but not elsewhere.
Thus, after a declaration def func[T](): pass
, the name T
is not available in
the module scope. Below, the semantics of generic objects are described
with more precision. The scope of type parameters is modeled with a special
function (technically, an annotation scope) that
wraps the creation of the generic object.
Generic functions, classes, and type aliases have a
__type_params__
attribute listing their type parameters.
Type parameters come in three kinds:
typing.TypeVar
, introduced by a plain name (e.g.,T
). Semantically, this represents a single type to a type checker.typing.TypeVarTuple
, introduced by a name prefixed with a single asterisk (e.g.,*Ts
). Semantically, this stands for a tuple of any number of types.typing.ParamSpec
, introduced by a name prefixed with two asterisks (e.g.,**P
). Semantically, this stands for the parameters of a callable.
typing.TypeVar
declarations can define bounds and constraints with
a colon (:
) followed by an expression. A single expression after the colon
indicates a bound (e.g. T: int
). Semantically, this means
that the typing.TypeVar
can only represent types that are a subtype of
this bound. A parenthesized tuple of expressions after the colon indicates a
set of constraints (e.g. T: (str, bytes)
). Each member of the tuple should be a
type (again, this is not enforced at runtime). Constrained type variables can only
take on one of the types in the list of constraints.
For typing.TypeVar
s declared using the type parameter list syntax,
the bound and constraints are not evaluated when the generic object is created,
but only when the value is explicitly accessed through the attributes __bound__
and __constraints__
. To accomplish this, the bounds or constraints are
evaluated in a separate annotation scope.
typing.TypeVarTuple
s and typing.ParamSpec
s cannot have bounds
or constraints.
All three flavors of type parameters can also have a default value, which is used
when the type parameter is not explicitly provided. This is added by appending
a single equals sign (=
) followed by an expression. Like the bounds and
constraints of type variables, the default value is not evaluated when the
object is created, but only when the type parameter's __default__
attribute
is accessed. To this end, the default value is evaluated in a separate
annotation scope. If no default value is specified
for a type parameter, the __default__
attribute is set to the special
sentinel object typing.NoDefault
.
The following example indicates the full set of allowed type parameter declarations:
def overly_generic[
SimpleTypeVar,
TypeVarWithDefault = int,
TypeVarWithBound: int,
TypeVarWithConstraints: (str, bytes),
*SimpleTypeVarTuple = (int, float),
**SimpleParamSpec = (str, bytearray),
](
a: SimpleTypeVar,
b: TypeVarWithDefault,
c: TypeVarWithBound,
d: Callable[SimpleParamSpec, TypeVarWithConstraints],
*e: SimpleTypeVarTuple,
): ...
8.10.1. Generic functions¶
Generic functions are declared as follows:
def func[T](arg: T): ...
This syntax is equivalent to:
annotation-def TYPE_PARAMS_OF_func():
T = typing.TypeVar("T")
def func(arg: T): ...
func.__type_params__ = (T,)
return func
func = TYPE_PARAMS_OF_func()
Here annotation-def
indicates an annotation scope,
which is not actually bound to any name at runtime. (One
other liberty is taken in the translation: the syntax does not go through
attribute access on the typing
module, but creates an instance of
typing.TypeVar
directly.)
The annotations of generic functions are evaluated within the annotation scope used for declaring the type parameters, but the function's defaults and decorators are not.
The following example illustrates the scoping rules for these cases, as well as for additional flavors of type parameters:
@decorator
def func[T: int, *Ts, **P](*args: *Ts, arg: Callable[P, T] = some_default):
...
Except for the lazy evaluation of the
TypeVar
bound, this is equivalent to:
DEFAULT_OF_arg = some_default
annotation-def TYPE_PARAMS_OF_func():
annotation-def BOUND_OF_T():
return int
# In reality, BOUND_OF_T() is evaluated only on demand.
T = typing.TypeVar("T", bound=BOUND_OF_T())
Ts = typing.TypeVarTuple("Ts")
P = typing.ParamSpec("P")
def func(*args: *Ts, arg: Callable[P, T] = DEFAULT_OF_arg):
...
func.__type_params__ = (T, Ts, P)
return func
func = decorator(TYPE_PARAMS_OF_func())
The capitalized names like DEFAULT_OF_arg
are not actually
bound at runtime.
8.10.2. Generic classes¶
Generic classes are declared as follows:
class Bag[T]: ...
This syntax is equivalent to:
annotation-def TYPE_PARAMS_OF_Bag():
T = typing.TypeVar("T")
class Bag(typing.Generic[T]):
__type_params__ = (T,)
...
return Bag
Bag = TYPE_PARAMS_OF_Bag()
Here again annotation-def
(not a real keyword) indicates an
annotation scope, and the name
TYPE_PARAMS_OF_Bag
is not actually bound at runtime.
Generic classes implicitly inherit from typing.Generic
.
The base classes and keyword arguments of generic classes are
evaluated within the type scope for the type parameters,
and decorators are evaluated outside that scope. This is illustrated
by this example:
@decorator
class Bag(Base[T], arg=T): ...
これは次と等価です:
annotation-def TYPE_PARAMS_OF_Bag():
T = typing.TypeVar("T")
class Bag(Base[T], typing.Generic[T], arg=T):
__type_params__ = (T,)
...
return Bag
Bag = decorator(TYPE_PARAMS_OF_Bag())
8.10.3. Generic type aliases¶
The type
statement can also be used to create a generic type alias:
type ListOrSet[T] = list[T] | set[T]
Except for the lazy evaluation of the value, this is equivalent to:
annotation-def TYPE_PARAMS_OF_ListOrSet():
T = typing.TypeVar("T")
annotation-def VALUE_OF_ListOrSet():
return list[T] | set[T]
# In reality, the value is lazily evaluated
return typing.TypeAliasType("ListOrSet", VALUE_OF_ListOrSet(), type_params=(T,))
ListOrSet = TYPE_PARAMS_OF_ListOrSet()
Here, annotation-def
(not a real keyword) indicates an
annotation scope. The capitalized names
like TYPE_PARAMS_OF_ListOrSet
are not actually bound at runtime.
脚注