+=
の標準表記とは異なる効果があると言われましたi = i +
。i += 1
と違う場合はありi = i + 1
ますか?
3 に答える
これは完全にオブジェクトに依存しますi
。
+=
__iadd__
メソッドを呼び出します(存在する場合-存在__add__
しない場合はフォールバックします)が、メソッド1または場合によってはメソッド2+
を呼び出します。__add__
__radd__
APIの観点からは、変更可能なオブジェクトを適切に変更する(変更されたオブジェクトを返す)__iadd__
ために使用されることになっていますが、何かの新しいインスタンスを返す必要があります。不変オブジェクトの場合、どちらのメソッドも新しいインスタンスを返しますが、古いインスタンスと同じ名前で新しいインスタンスを現在の名前空間に配置します。これが理由です__add__
__iadd__
i = 1
i += 1
インクリメントするようi
です。実際には、新しい整数を取得して「上に」割り当てi
ます。古い整数への参照が1つ失われます。この場合、i += 1
はとまったく同じi = i + 1
です。しかし、ほとんどの可変オブジェクトでは、それは別の話です。
具体的な例として:
a = [1, 2, 3]
b = a
b += [1, 2, 3]
print a #[1, 2, 3, 1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
に比べ:
a = [1, 2, 3]
b = a
b = b + [1, 2, 3]
print a #[1, 2, 3]
print b #[1, 2, 3, 1, 2, 3]
最初の例では、同じオブジェクトb
を参照しているので、で使用すると、実際に変更されます(そして、その変更も確認されます-結局のところ、同じリストを参照しています)。ただし、2番目のケースでは、これを行うと、参照しているリストが取得され、新しいリストと連結されます。次に、連結されたリストを現在の名前空間に-として格納します。前の行が何であったかは関係ありません。a
+=
b
b
a
b = b + [1, 2, 3]
b
[1, 2, 3]
b
b
1式x + y
で、x.__add__
が実装されていない場合、またはがx.__add__(y)
返さNotImplemented
れ、 x
タイプy
が異なる場合は、x + y
を呼び出そうとしますy.__radd__(x)
。だから、あなたが持っている場合
foo_instance += bar_instance
Foo
が実装されていない場合、__add__
または__iadd__
ここでの結果はと同じです
foo_instance = bar_instance.__radd__(bar_instance, foo_instance)
2式foo_instance + bar_instance
で、のタイプが(eg )のタイプのサブクラスである場合、bar_instance.__radd__
は前に試行されます。これの理論的根拠は、ある意味で「より高いレベルの」オブジェクトであるため、の動作をオーバーライドするオプションを取得する必要があるということです。foo_instance.__add__
bar_instance
foo_instance
issubclass(Bar, Foo)
Bar
Foo
Bar
Foo
裏で、i += 1
このようなことをします:
try:
i = i.__iadd__(1)
except AttributeError:
i = i.__add__(1)
このi = i + 1
ようなことをしている間:
i = i.__add__(1)
これは少し単純化しすぎていますが、あなたは考えを理解します。Pythonは、メソッドと+=
を作成することによって、型に特別に処理する__iadd__
方法を提供します__add__
。
のような不変の型は、list
で自分自身を変異させます__iadd__
(そして、self
非常にトリッキーなことをしている場合を除いて、を返します)が、のような不変の型は、int
それを実装しません。
例えば:
>>> l1 = []
>>> l2 = l1
>>> l1 += [3]
>>> l2
[3]
l2
はと同じオブジェクトであり、l1
変更したためl1
、も変更しましたl2
。
だが:
>>> l1 = []
>>> l2 = l1
>>> l1 = l1 + [3]
>>> l2
[]
ここでは、変異していませんl1
。代わりに、新しいリストを作成しl1 + [3]
、名前をリバウンドしてそれをポイントし、元のリストl1
をポイントしたままにします。l2
(この+=
バージョンでは、再バインドも行っl1
ていました。その場合は、既にバインドされているものと同じlist
ものに再バインドしていたため、通常はその部分を無視できます。)
i += x
これは、以下と直接比較する例ですi = i + x
。
def foo(x):
x = x + [42]
def bar(x):
x += [42]
c = [27]
foo(c); # c is not changed
bar(c); # c is changed to [27, 42]