x = x+1
Python では、書き込みとの間に違い (セマンティクス、効率など) はありx += 1
ますか?
4 に答える
はい。のクラスがどのようにx
コーディングされているかに応じて、短い形式には、合計を表す新しいオブジェクトを作成して同じ名前に再バインドする代わりに、x をその場で変更するオプションがあります。これは、複数の変数がすべて同じオブジェクトを参照している場合 (たとえば、リストを使用する場合) に影響します。
>>> a = b = []
>>> a += [5]
>>> a
[5]
>>> b
[5]
>>> a = a + [5]
>>> a
[5, 5]
>>> b
[5]
これは、オペレータが舞台裏でさまざまな魔法のメソッドを呼び出すために発生します: +
or __add__
(__radd__
どちらの引数も変更しないと予想されます) と+=
try __iadd__
(必要に応じて変更が許可されます) を呼び出してから、ロジック if isself
にフォールバックします。そこにいない。+
__iadd__
整数と浮動小数点数ではほぼ同じですが、次の場合は次のlists
とおりです。
lis = lis+['foo']
連結して新しいリストを作成しlis
、['foo']
結果をに代入しますlis
と :
lis += [foo]
と同等ですlis.extend([foo])
>>> lis = [1,2,3]
>>> id(lis)
3078880140L
>>> lis += ['foo'] #or lis.extend(['foo'])
>>> id(lis) #same object
3078880140L
>>> lis = [1,2,3]
>>> id(lis)
3078880076L
>>> lis = lis+['foo']
>>> id(lis) #new object
3078880012L
はい、それらは異なるバイトコードにコンパイルされる異なる演算子です:
>>> import dis
>>> def test1(x):
... x = x + 1
...
>>> def test2(x):
... x += 1
...
>>> dis.dis(test1)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (1)
6 BINARY_ADD
7 STORE_FAST 0 (x)
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
>>> dis.dis(test2)
2 0 LOAD_FAST 0 (x)
3 LOAD_CONST 1 (1)
6 INPLACE_ADD
7 STORE_FAST 0 (x)
10 LOAD_CONST 0 (None)
13 RETURN_VALUE
int
この場合、 s は不変であるため、大きな違いはありません。理論的には、(インタープリターに応じて) さまざまな方法で実装できますが、値の操作方法は変わりません。
一般に、それらは完全に異なることを実行するように実装できます (+
マジック メソッド__add__()
と+=
を使用して実装されます__iadd()__
)。たとえば、ほとんどの可変コンテナーでは、同じオブジェクトを参照する別の名前がある場合、大きな違いが生じます。
>>> x = []
>>> y = x
>>> x += [1]
>>> y
[1]
>>> x = x + [1]
>>> y
[1]
>>> x
[1, 1]
x
に割り当てるとy
、両方が同じリストを指していることがわかります。を使用する+=
と、リストが拡張され、両方が変更されます。に新しい値を割り当てると、 は元の値を指し、変更されませんx
。y
と には別々の演算子があるため、それらは異なり+
ます+=
。を使用すると、インタープリターはそれを のようにx = x + 1
扱いますが、 のコピーを作成する必要がないため、はるかに効率的です。x = x.__add__(1)
x += 1
x = x.__iadd(1)
x