のような「拡張された」代入演算子+=
は、2000年10月にリリースされたPython 2.0で導入されました。設計と根拠については、PEP 203で説明されています。これらのオペレーターの宣言された目標の1つは、インプレース操作のサポートでした。書き込み
a = [1, 2, 3]
a += [4, 5, 6]
そのa
場でリストを更新することになっています。これは、リストへの他の参照がある場合に重要ですa
。たとえば、a
が関数の引数として受け取られた場合です。
ただし、整数や文字列を含む多くのPythonタイプは不変であるため、操作が常に行われるとは限りません。たとえばi += 1
、整数のi
場合、適切に操作できない可能性があります。
要約すると、拡張代入演算子は可能な場合は適切に機能し、それ以外の場合は新しいオブジェクトを作成することになっています。これらの設計目標を容易にするために、式x += y
は次のように動作するように指定されました。
x.__iadd__
が定義されている場合、x.__iadd__(y)
評価されます。
- それ以外の場合、
x.__add__
実装されている場合x.__add__(y)
いる評価されます。
- それ以外の場合、
y.__radd__
実装されている場合y.__radd__(x)
いる評価されます。
- そうでない場合はエラーが発生します。
このプロセスで取得された最初の結果x
は、(その結果がNotImplemented
シングルトンで場合。この場合、ルックアップは次のステップに進みます)。
このプロセスにより、インプレース変更をサポートする型でを実装でき__iadd__()
ます。インプレース変更をサポートしない型は、新しいマジックメソッドを追加する必要がありません。Pythonは自動的に本質的にフォールバックするためです。x = x + y
。
それでは、最後に実際の質問に行きましょう。なぜ拡張代入演算子を使ってタプルをリストに追加できるのでしょうか。メモリから、これの歴史はおおよそ次のようでした:このlist.__iadd__()
メソッドはlist.extend()
、Python 2.0の既存のメソッドを単に呼び出すように実装されました。Python 2.1でイテレータが導入されたとき、list.extend()
メソッドは任意のイテレータを受け入れるように更新されました。これらの変更の最終結果はmy_list += my_tuple
、Python 2.1から機能しました。のlist.__add__()
ただし、メソッドは、任意の反復子を右側の引数としてサポートすることは想定されていませんでした。これは、強く型付けされた言語には不適切と見なされていました。
個人的には、拡張演算子の実装はPythonでは少し複雑になりすぎたと思います。それは多くの驚くべき副作用を持っています、例えばこのコード:
t = ([42], [43])
t[0] += [44]
2行目は、発生させTypeError: 'tuple' object does not support item assignment
、しかし、動作が正常とにかく行われる - t
となり([42, 44], [43])
エラーが発生行を実行した後。