#
3 代入文 (assignment statement)

代入文 は、名前を値に (再) 束縛したり、 変更可能なオブジェクトの属性や要素を変更したりするために使われます:

  assignment_stmt | ::= | (target_list "=")+ expression_list
  target_list | ::= | target ("," target)* [","]
  target | ::= | identifier
  |  | `| "(" target_list ")"`
  |  | `| "[" target_list "]"`
  |  | `| attributeref`
  |  | `| subscription`
  |  | `| slicing`

  Download entire grammar as text.

(末尾の三つのシンボルの構文については 5.3 節を 参照してください。)

代入文は式のリスト (これは単一の式でも、 カンマで区切られた式リストでもよく、後者はタプルになることを 思い出してください) を評価し、得られた単一の結果オブジェクトを ターゲット (target) のリストに対して左から右へと代入してゆきます。

代入はターゲット (リスト) の形式に従って再帰的に行われます。 ターゲットが変更可能なオブジェクト (属性参照、添字表記、またはスライス) の一部である場合、この変更可能なオブジェクトは最終的に代入を 実行して、その代入が有効な操作であるか判断しなければなりません。 代入が不可能な場合には例外を発行することもできます。型ごとに みられる規則や、送出される例外は、そのオブジェクト型定義 で与えられています ( 3.2 節を参照してください).

ターゲットリストへのオブジェクトの代入は、以下のようにして再帰的に 定義されています。

- ターゲットリストが単一のターゲットからなる場合: オブジェクトはその ターゲットに代入されます。

- ターゲットリストが、カンマで区切られた複数のターゲットからなる リストの場合: オブジェクトはターゲットリスト中のターゲット数と 同じ数の要素からなるシーケンスでなければならず、その各要素は左から 右へと対応するターゲットに代入されます。(これは Python 1.5 で緩和された規則です; 以前のバージョンでは、代入するオブジェクトは タプルでなければなりませんでした。文字列もシーケンスなので、今では "`a, b = "xy"`" のような代入は文字列が正しい長さを持つ限り 正規の操作になります。)

単一のターゲットへの単一のオブジェクトの代入は、以下のようにして 再帰的に定義されています。

- ターゲットが識別子 (名前) の場合:

  - 名前が現在のコードブロック内の `global` 文に書かれて いない場合: 名前は現在のローカル名前空間内のオブジェクトに 束縛されます。

  - それ以外の場合: 名前は現在のグローバル名前空間内のオブジェクトに 束縛されます。

  名前がすでに束縛済みの場合、再束縛 (rebind) がおこなわれます。 再束縛によって、以前その名前に束縛されていたオブジェクトの 参照カウント (reference count) がゼロになった場合、オブジェクトは 解放 (deallocate) され、デストラクタ (destructor) が (存在すれば) 呼び出されます。

- ターゲットが丸括弧や角括弧で囲われたターゲットリストの場合: オブジェクトはターゲットリスト中のターゲット数と 同じ数の要素からなるシーケンスでなければならず、その各要素は左から 右へと対応するターゲットに代入されます。

- ターゲットが属性参照の場合: 参照されている一次語の式 が値評価されます。値は代入可能な属性を伴うオブジェクトでなければ なりません; そうでなければ、 `TypeError` が送出されます。 次に、このオブジェクトに対して、被代入オブジェクトを指定した属性 に代入してよいか問い合わせます; 代入を実行できない場合、 例外 (通常は `AttributeError` ですが、必然ではありません) を送出します。

- ターゲットが添字表記の場合: 参照されている一次語の式 が値評価されます。まず、値は変更可能な (リストのような) シーケンスオブジェクト か、 (辞書のような) マップオブジェクトでなければなりません。 次に、添字表記の表す式が値評価されます。

  一次語が変更可能な (リストのような) シーケンスオブジェクトの場合、 まず添字は整数でなければなりません。添字が負数の場合、シーケンスの 長さが加算されます。添字は最終的に、シーケンスの長さよりも小さな 非負の整数でなくてはなりません。次に、添字をインデクスに 持つ要素に非代入オブジェクトを代入してよいか、シーケンスに問い合わせ ます。範囲を超えたインデクスに対しては`IndexError` が送出されます (添字指定されたシーケンスに代入を行っても、 リスト要素の新たな追加はできません)。

  一次語が (辞書のような) マップオブジェクトの場合、まず添字は マップのキー型と互換性のある型でなくてはなりません。 次に、添字を被代入オブジェクトに関連付けるようなキー/データ の対を生成するようマップオブジェクトに問い合わせます。 この操作では、既存のキー/値の対を同じキーと別の値で置き換えても よく、(同じ値を持つキーが存在しない場合) 新たなキー/値の対を挿入しても かまいません。

- ターゲットがスライスの場合: 参照されている一次語の式 が値評価されます。まず、値は変更可能な (リストのような) シーケンスオブジェクト でなければなりません。被代入オブジェクトは同じ型を持ったシーケンスオブジェクト でなければなりません。次に、スライスの下境界と上境界を示す式があれば 評価されます; デフォルト値はそれぞれゼロとシーケンスの長さです。 上下境界は整数にならなければなりません。いずれかの境界が負数に なった場合、シーケンスの長さが加算されます。最終的に、境界は ゼロからシーケンスの長さまでの内包になるようにクリップされます。 最後に、スライスを被代入オブジェクトで置き換えてよいかシーケンスオブジェクトに 問い合わせます。オブジェクトで許されている限り、スライスの長さは 被代入シーケンスの長さと異なっていてよく、この場合にはターゲットシーケンスの 長さが変更されます。

(現在の実装では、ターゲットの構文は式の構文と同じであるとみなされて おり、無効な構文はコード生成フェーズ中に詳細なエラーメッセージを 伴って拒否されます。)

警告: 代入の定義では、左辺値と右辺値がオーバラップするような代入 (例えば、"`a, b = b, a`" を行うと、二つの変数を入れ替えます) を 定義しても `安全 (safe)' に代入できますが、代入対象となる 変数群 の間で オーバラップがある場合は安全ではありません！ 例えば、以下のプログラムは "`[0, 2]`" を出力してしまいます:

    x = [0, 1]
    i = 0
    i, x[i] = 1, 2
    print x