Home > Article > Backend Development > Is the Python expression i += x equivalent to i = i + x?
Are the Python expressions i += x equivalent to i = i + x? If your answer is yes, then congratulations, you are 50% correct. Why do you say it is only half correct? According to our general understanding, they are equivalent. There are no similarities or differences between the two when it comes to integer operations, but is it the same for list operations? First look at the following two pieces of code:
Code 1
>>> l1 = range(3) >>> l2 = l1 >>> l2 += [3] >>> l1 [0, 1, 2, 3] >>> l2 [0, 1, 2, 3]
Code 2
>>> l1 = range(3) >>> l2 = l1 >>> l2 = l2 + [3] >>> l1 [0, 1, 2] >>> l2 [0, 1, 2, 3]
The values of l2 in code 1 and code 2 are the same, but the value of l1 is different. Different, it means that i + = x and i = i + x are not equivalent. So under what circumstances are they equivalent and under what circumstances are they not equivalent?
Before clarifying this issue, you must first understand two concepts: mutable objects and immutable objects.
There are three common attributes that any object in Python has: unique identifier, type, and value.
Unique identification: used to identify the uniqueness of an object in memory. It will not change after the object is created. The function id() can view the unique identification of the object.
Type: Determination The operations supported by the object are different. Different types of objects support different operations. For example, lists can have a length attribute, but integers do not. Similarly, once the type of an object is determined, it will not change. The function type() can return the type information of the object.
The value of an object is different from a unique identifier. Not all object values are immutable. The values of some objects can be changed through certain operations. Objects whose values can change are called mutable objects. (mutable), an object whose value cannot be changed is called an immutable object (immutable)
Immutable object (immutable)
For an immutable object, the value is always the value when it was first created. , any operation on this object will result in the creation of a new object.
>>> a = 1 >>> id(a) 32574568 >>> a += 1 >>> id(a) 32574544
The integer "1" is an immutable object. When initially assigned, a points to the integer object 1, but after performing the += operation on the variable a, a points to another integer object 2, but the object 1 Still nothing has changed there, and variable a already points to a new object 2. Common immutable objects include: int, tuple, set, str.
Mutable object (mutable)
The value of a mutable object can be dynamically changed through certain operations, such as a list object, which can be continuously changed through the append method. Add elements to the list continuously, and the value of the list is constantly changing. When a variable object is assigned to two variables, they share the same instance object and point to the same memory address. When operating on any one of the variables , and it will also affect another variable.
>>> 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
+= The operation will first try to call the object's __iadd__ method. If there is no such method, then try to call the __add__ method. Let's take a look at these two methods first. What is the difference?
The difference between __add__ and __iadd__
__add__ method receives two parameters and returns their sum. The values of the two parameters will not change.
__iadd__ method also receives two parameters, but it is an in-place operation, which means that it will change the value of the first parameter, because this requires the object to be mutable, so there is no need for immutable objects __iadd__ method.
>>> hasattr(int, '__iadd__') False >>> hasattr(list, '__iadd__') True
Obviously, integer objects do not have __iadd__, but list objects provide the __iadd__ method.
>>> l2 += [3] # 代码1:使用__iadd__,l2的值原地修改
The += operation in code 1 calls the __iadd__ method, which will modify the value of the object pointed to by l2 in place
>>> l2 = l2 + [3] # 代码2:调用 __add__,创建了一个新的列表,赋值给了l2
The + operation in code 2 calls the __add__ method, which returns a new object. The original object remains unchanged. l1 still points to the original object, and l2 already points to a new object.
The above is the difference between the expressions i += x and i = i + x. Therefore, there will be potential bugs when performing += operations on lists, because l1 will change due to changes in l2, just like the parameters of a function should not use variable objects as keyword parameters.