Pythonで+=をオーバーライドすることは可能ですか?
4 に答える
はい、__iadd__
メソッドをオーバーライドします。例:
def __iadd__(self, other):
self.number += other.number
return self
上記の回答で正しく与えられていることに加えて、__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__
何が起こっているのかを理解していない限り、結果として生じるバグは修正するのに悪夢になる可能性があります。
オーバーロードに加えて__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
か?
http://docs.python.org/reference/datamodel.html#emulating-numeric-types
たとえば、ステートメントx + = yを実行するには、xは__iadd __()メソッドを持つクラスのインスタンスであり、x .__ iadd __(y)が呼び出されます。