84

Pythonで+=をオーバーライドすることは可能ですか?

4

4 に答える 4

141

はい、__iadd__メソッドをオーバーライドします。例:

def __iadd__(self, other):
    self.number += other.number
    return self    
于 2009-06-26T02:08:45.960 に答える
39

上記の回答で正しく与えられていることに加えて、__iadd__がオーバーライドされた場合、操作はメソッドx += yの終わりで終了しないことを明示的に明確にする価値があります。__iadd__

代わりに、で終わりx = x.__iadd__(y)ます。つまり、Pythonは__iadd__、実装が完了した後、「追加」するオブジェクトに実装の戻り値を割り当てます。

これは、操作の左側を変更x += yして、最後の暗黙のステップが失敗する可能性があることを意味します。リスト内にあるものに追加するときに何が起こるかを考えてみましょう。

>>> x[1] += y # x has two items

ここで、__iadd__実装(でのオブジェクトのメソッドx[1])が誤ってまたは意図的x[0]にリストの先頭から最初の項目()を削除した場合、Pythonは__iadd__メソッドを実行します)そしてその戻り値をに割り当てようとしx[1]ます。これはもう存在しません(になりますx[0])。結果としてÌndexError

または、上記の例の__iadd__最初に何かを挿入した場合x、オブジェクトはでx[2]はなくx[1]、になり、以前の値はすべてにx[0]なり、呼び出しx[1]の戻り値が割り当てられます。__iadd__

何が起こっているのかを理解していない限り、結果として生じるバグは修正するのに悪夢になる可能性があります。

于 2015-07-21T18:18:05.160 に答える
14

オーバーロードに加えて__iadd__(自分自身を返すことを忘れないでください!)、__add__x +=yはx=x + yのように機能するため、フォールバックすることもできます。(これは、+ =演算子の落とし穴の1つです。)

>>> class A(object):
...   def __init__(self, x):
...     self.x = x
...   def __add__(self, other):
...     return A(self.x + other.x)
>>> a = A(42)
>>> b = A(3)
>>> print a.x, b.x
42 3
>>> old_id = id(a)
>>> a += b
>>> print a.x
45
>>> print old_id == id(a)
False

それは専門家をつまずかせさえします:

class Resource(object):
  class_counter = 0
  def __init__(self):
    self.id = self.class_counter
    self.class_counter += 1

x = Resource()
y = Resource()

x.id、、y.idおよびにどのような値を期待しますResource.class_counterか?

于 2009-06-26T02:26:01.510 に答える
5

http://docs.python.org/reference/datamodel.html#emulating-numeric-types

たとえば、ステートメントx + = yを実行するには、xは__iadd __()メソッドを持つクラスのインスタンスであり、x .__ iadd __(y)が呼び出されます。

于 2009-06-26T02:09:16.600 に答える