1. ホーム
  2. python

[解決済み] for'ループでi = i + 1とi += 1の違いは何ですか?[重複しています]。

2022-02-07 20:14:07

質問

今日、不思議なことを発見したのですが、どなたかこの違いについて教えていただけませんか?

import numpy as np

A = np.arange(12).reshape(4,3)
for a in A:
    a = a + 1

B = np.arange(12).reshape(4,3)
for b in B:
    b += 1

を実行した後、それぞれの for のループになります。 A は変更されていませんが B は、各要素に1つずつ追加されています。実際に使っているのは B の中で初期化されたNumPyの配列に書き込むためのバージョンです。 for のループになります。

どのように解決するのですか?

違いは、データ構造そのものを変更する場合(インプレース操作)です。 b += 1 であるのに対し、もう一方は 再割り当て 変数 a = a + 1 .


念のため。

x += y 常に がインプレース操作を行う場合、(少なくとも)3つの例外があります。

  • もし x は実装されていません。 アン __iadd__ メソッドを使用する場合 x += y 文は、単に x = x + y . これは、次のような場合です。 x のようなものでした。 int .

  • もし __iadd__ を返します。 NotImplemented にフォールバックし、Pythonは x = x + y .

  • __iadd__ メソッドは、理論的にはそのままでは動作しないように実装することができます。そんなことしたら、本当に気持ち悪いですけどね。

たまたまあなたの bnumpy.ndarray を実装している __iadd__ を作成し、それ自体を返すので、2回目のループでは元の配列をインプレースで変更します。

これについては Python documentation of "Emulating Numeric Types" .

<ブロッククオート

これらの [... __i*__ ] メソッドは、拡張された算術代入を実装するために呼び出されます ( += , -= , *= , @= , /= , //= , %= , **= , <<= , >>= , &= , ^= , |= ). これらのメソッドは、インプレースで操作を行い(selfを変更)、その結果(selfである可能性もあるが、そうである必要はない)を返そうとするはずである。特定のメソッドが定義されていない場合、拡張された代入は通常のメソッドにフォールバックします。例えば、x がクラスのインスタンスで __iadd__() メソッドを使用します。 x += y と同じです。 x = x.__iadd__(y) . それ以外の場合は x.__add__(y)y.__radd__(x) の評価と同様、考慮されます。 x + y . 特定の状況では,補強された代入は予期せぬエラーを引き起こすことがあります ( なぜ a_tuple[i] += ["item"] は、加算がうまくいったときに例外を発生させるのですか? ) が、実はこの動作はデータモデルの一部なのです。