8

次のセッションを検討してください。違いはどのように説明されていますか?私はそれa += bが の構文糖衣であると考えました (したがって、同等です) a = a + b。明らかに私は間違っています。

>>> import numpy as np
>>> a  = np.arange(24.).reshape(4,6)
>>> print a
[[  0.   1.   2.   3.   4.   5.]
 [  6.   7.   8.   9.  10.  11.]
 [ 12.  13.  14.  15.  16.  17.]
 [ 18.  19.  20.  21.  22.  23.]]
>>> for line in a:
...     line += 100
...
>>> print a #a has been changed
[[ 100.  101.  102.  103.  104.  105.]
 [ 106.  107.  108.  109.  110.  111.]
 [ 112.  113.  114.  115.  116.  117.]
 [ 118.  119.  120.  121.  122.  123.]]
>>>
>>> for line in a:
...     line = line + 999
...
>>> print a #a hasn't been changed
[[ 100.  101.  102.  103.  104.  105.]
 [ 106.  107.  108.  109.  110.  111.]
 [ 112.  113.  114.  115.  116.  117.]
 [ 118.  119.  120.  121.  122.  123.]]

ありがとうございました

4

2 に答える 2

15

+演算子を使用する__add__と、新しいオブジェクトを作成し、元のオブジェクトを変更しない特別なメソッドが呼び出されます。

一方、+=演算子を使用__iadd__すると、新しいオブジェクトを作成するのではなく、可能であればオブジェクトを変更する必要がある呼び出しが発生します。

__add__

これらのメソッドは、バイナリ算術演算 (+、-、​​、//、%、divmod()、pow()、**、<<、>>、&、^、|) を実装するために呼び出されます。たとえば、式 x + y を評価するには、x は __add__() メソッドを持つクラスのインスタンスであり、x.__add__(y) が呼び出されます。

__iadd__

これらのメソッドは、拡張算術代入 (+=、-=、*=、/=、//=、%=、**=、<<=、>>=、&=、^=、|=) を実装するために呼び出されます。 )。これらのメソッドは、その場で操作を実行し (self を変更)、結果を返します (self である必要はありませんが、self である必要はありません)。

もちろん、必要に応じて実装して他の動作を行うことは可能__add__です__iadd__が、観察するのは標準的で推奨される方法です。そして、はい、初めて見たときは少し驚きました。

于 2010-08-10T09:18:23.360 に答える
7

あなたは間違っていません.時には本当にa += b構文糖衣a = a + bです.

+オペレーターは特別なメソッド__add__を呼び出し、オペレーター+=はインプレースの特別なメソッドを呼び出そうとしますが、定義されていない__iadd__場合に拡張する価値があると思います。__iadd__

文字列や整数などの不変型の場合など、インプレース演算子が定義されていない場合は、__add__代わりに呼び出されます。したがって、これらの型の場合、a += b実際には構文糖衣ですa = a + b。このおもちゃのクラスは要点を示しています。

>>> class A(object):
...     def __add__(self, other):
...         print "In __add__ (not __iadd__)"
...         return A()
...
>>> a = A()
>>> a = a + 1
In __add__ (not __iadd__)
>>> a += 1
In __add__ (not __iadd__)

これは、不変の型に期待される動作です。これは紛らわしいかもしれませんが、別の方法+=として不変の型を禁止することもできます。これは、文字列や整数で使用できないことを意味するため、残念です!

別の例として、これはリストとタプルの違いにつながります。どちらも をサポート+=していますが、変更できるのはリストだけです。

>>> a = (1, 2)
>>> b = a
>>> b += (3, 4)   # b = b + (3, 4)   (creates new tuple, doesn't modify)
>>> a
(1, 2)

>>> a = [1, 2]
>>> b = a
>>> b += [3, 4]   # calls __iadd___ so modifies b (and so a also)
>>> a
[1, 2, 3, 4]

もちろん、他のすべてのインプレース演算子、、、、、などにも同じこと-=が言え*=ます。//=%=

于 2010-08-10T10:50:11.720 に答える