15

Python 拡張代入について興味深いことに出くわしました+=

a += baが「より単純な」データ型である場合、自動データ型変換が常に行われるとは限らないようですが、常にa = a + b機能するようです

変換が行われるケース

a = 1
b = 1j

a = 1
b = 0.5

変換しない場合

from numpy import array
a = array([0, 0 ,0])
b = array([0, 0, 1j])

の後a += ba複素行列ではなく、整数行列として残ります

私は以前a += bは と同じだと思っa = a + bていましたが、基本的な実装におけるそれらの違いは何ですか?

4

4 に答える 4

16

演算子について+、Python は、オブジェクトが実装できる 3 つの「特別な」メソッドを定義します。

  • __add__: 2 つの項目を追加します (+演算子)。を実行するa + bと、 の__add__メソッドが引数としてa呼び出されbます。
  • __radd__: 反映された追加; for のa + b場合、 の__radd__メソッドがインスタンスとしてb呼び出されaます。aこれは、追加の方法がわからず、2 つのオブジェクトが異なるタイプである場合にのみ使用されます。
  • __iadd__: インプレース追加; a += b結果が左の変数に代入される場所に使用されます。これは、より効率的な方法で実装できる可能性があるため、個別に提供されています。たとえば、aがリストの場合、a += bは と同じa.extend(b)です。ただし、この場合、 は変更されないため、拡張する前にc = a + bのコピーを作成する必要があります。実装しない場合は、代わりにPython が呼び出すだけであることに注意してください。aa__iadd____add__

したがって、これらの異なる操作は別々のメソッドで実装されるため、完全に異なること、またはおそらくこの場合はわずかに異なることを行うようにそれらを実装することが可能です (ただし、一般的には悪い習慣です) 。

他の人は、NumPy を使用していると推測し、その動作を説明しました。ただし、基になる実装について質問しました。と同じではない場合がある理由がわかったと思います。ちなみに、同様のメソッドのトリオは、他の操作にも実装できます。サポートされているすべてのインプレース メソッドのリストについては、このページを参照してください。a += ba = a + b

于 2010-12-07T23:04:19.057 に答える
8

arrayである場合numpy.array(実際には指定しません)、発生している問題は、これらの配列が型を変更できないためです。型指定子なしで配列を作成すると、型が推測されます。次に、タイプがサポートしていない操作を実行しようとすると (complex など、より大きなドメインを持つタイプに追加するなど)、numpy は計算を実行することを認識しますが、結果はそのタイプにのみ格納できることも認識しますより大きなドメインで。結果が合わないと不平を言います(とにかく、私のマシンでは、そのような割り当てを初めて行うとき)。通常の追加を行う場合、いずれにしても新しい配列を作成する必要があり、numpy はそれに正しい型を与えます。

>>> a=numpy.array([1])
>>> a.dtype
dtype('int32')
>>> b=numpy.array([1+1j])
>>> b.dtype
dtype('complex128')
>>> a+b
array([ 2.+1.j])
>>> (a+b).dtype
dtype('complex128')
>>> a+=b
>>> a
array([2])
>>> a.dtype
dtype('int32')
>>> 
于 2010-12-07T22:57:46.700 に答える
1

a = a + bとの違いa += bは、後者の追加は可能な限り「その場で」行われるということです。つまり、 object を変更することaです。これはリストで簡単に確認できます。

a = b = [1, 2]
a += [3]
print b # [1, 2, 3]
a = b = [1, 2]
a = a + [3]
print b # [1, 2]
于 2010-12-07T22:53:29.290 に答える
0

Rafe Kettler の答えは正しいですが、b に追加した後、a=[0,0,0] を取得できたようです (投稿によると)。

numpy または scipy を使用している場合 (arrayここでどの配列が作成されているかを見て疑問に思うため、これを言います)、これは「正常」であり、警告を発生させる必要があります。

ComplexWarning: 複素数を実数にキャストすると、虚数部分が破棄されます

于 2010-12-07T22:49:51.197 に答える