この記事では主に、Python における式 i += x と i = i + x が同等であるかどうかについて、サンプルコードを通して詳しく紹介しています。それが必要です、友達、一緒に見てみましょう。
はじめに
最近、非常に単純そうに見えて実は深い意味を持つ質問を目にしました。その質問は、Python の式 i += x と i = i + x は同等ですか?というものでした。答えが「はい」の場合、おめでとうございます。半分しか正解していないのはなぜですか。 私たちの一般的な理解によれば、整数演算に関しては両者に類似点も相違点もありませんが、リスト演算についても同様でしょうか。
まず、次の 2 つのコードを見てください:
コード 1
>>> l1 = range(3) >>> l2 = l1 >>> l2 += [3] >>> l1 [0, 1, 2, 3] >>> l2 [0, 1, 2, 3]
コード 2
>>> l1 = range(3) >>> l2 = l1 >>> l2 = l2 + [3] >>> l1 [0, 1, 2] >>> l2 [0, 1, 2, 3]
コード 1 とコード 2 の l2 の値は同じです。しかし l1 の値は異なります 異なるということは、i + = x と i = i + x が等価ではないことを意味します。では、どのような状況では等価であり、どのような状況では等価ではないのでしょうか。
この問題を明確にする前に、まず変更可能なオブジェクトと不変オブジェクトという 2 つの概念を理解する必要があります。
Python のオブジェクトには、一意の識別子、型、値という 3 つの共通属性があります。
一意の識別: はメモリ内のオブジェクトの一意性を識別するために使用されます。関数 id() はオブジェクトの一意の識別子を表示できます。 :
決定 オブジェクトによってサポートされる操作は異なります。たとえば、リストには長さ属性を含めることができますが、整数にはサポートする操作が異なります。同様に、オブジェクトの型が決定されると、関数 type() はオブジェクトの型情報を返すことができます。オブジェクトの値は一意の識別子とは異なります。一部のオブジェクトの値は、特定の操作によって変更できるわけではありません。その値を変更可能なオブジェクトと呼びます。値を変更できないオブジェクトは、不変オブジェクト (immutable) と呼ばれます不変オブジェクト (immutable)
不変オブジェクトの場合、値は常に最初に作成されたときの値であり、オブジェクトに対する操作はすべて新しいオブジェクトの作成。>>> a = 1 >>> id(a) 32574568 >>> a += 1 >>> id(a) 32574544整数「1」は、最初に割り当てられたとき、a は整数オブジェクト 1 を指しますが、変数 a に対して += 演算を実行すると、a は別の整数オブジェクト 2 を指します。オブジェクト 1 まだ何も変更されておらず、変数 a はすでに新しいオブジェクト 2 を指しています。一般的な不変オブジェクトには、int、tuple、set、str が含まれます。 可変オブジェクト (mutable)
可変オブジェクトの値は、append メソッドを通じてリスト オブジェクトを継続的にリストに追加するなど、特定の操作を通じて動的に変更できます。常に変化している間、可変オブジェクトが 2 つの変数に割り当てられると、それらは同じインスタンス オブジェクトを共有し、同じメモリ アドレスを指します。一方の変数を操作すると、もう一方の変数にも影響します。
>>> x = range(3)
>>> y = x
>>> id(x)
139726103041232
>>> id(y)
139726103041232
>>> x.append(3)
>>> x
[0, 1, 2, 3]
>>> y
[0, 1, 2, 3]
>>> id(x)
139726103041232
>>> id(y)
139726103041232
可変オブジェクトと不変オブジェクトを理解した後、質問自体に戻って、+= と + の違いは何ですか?
+= オペレーションは、まずオブジェクトの __iadd__ メソッドの呼び出しを試みます。そのようなメソッドがない場合は、__add__ メソッドの呼び出しを試みます
まず、2 つのメソッドの違いを見てみましょう。
__add__ と __iadd__ の違い
__add__ メソッドは 2 つのパラメータを受け取り、その合計を返します。両方のパラメータの値は変わりません。__iadd__ メソッドも 2 つのパラメーターを受け取りますが、これはインプレース操作であり、最初のパラメーターの値を変更することを意味します。これは、オブジェクトが変更可能である必要があるため、不変オブジェクト用の __iadd_ はありません。 _方法。
>>> hasattr(int, '__iadd__') False >>> hasattr(list, '__iadd__') True
りー
代码1中的 += 操作调用的是__iadd__方法,他会原地修改l2指向的那个对象本身的值
>>> l2 = l2 + [3] # 代码2:调用 __add__,创建了一个新的列表,赋值给了l2
而代码2中的 + 操作调用的是 __add__ 方法,该方法会返回一个新的对象,原来的对象保持不变,l1还是指向原来的对象,而l2已经指向一个新的对象。
以上就是表达式 i += x 与 i = i + x 的区别。因此对于列表进行 += 操作时,会存在潜在的bug,因为l1会因为l2的变化而发生改变,就像函数的参数不宜使用可变对象作为关键字参数一样。
更多详解Python中表达式i += x与i = i + x是否等价相关文章请关注PHP中文网!