Add to list against Increment

Given in Python:

element = element + [0] 

should be equal to:

 element += [0] 

Why does one of them change the list, and the other does not? Here is an example:

 >>> a = [[0, 0], [0,0]] >>> for element in a: ... element = element + [0] ... >>> a [[0, 0], [0, 0]] 

a does not change. But if I increase:

 >>> a = [[0, 0], [0,0]] >>> for element in a: ... element += [0] ... >>> a [[0, 0, 0], [0, 0, 0]] 

a modified.

Thanks Frank

+6
source share
3 answers

This is a fun side effect of += operatior that calls __iadd__ instead of __add__ .

The operator x = x + y equivalent to x = x.__add__(y) , and x += y equivalent to x = x.__iadd__(y) .

This allows the list class to optimize += by expanding the existing one (ex, x += y roughly equivalent to the list x.extend(y) ) instead of creating a completely new list (what + needs to be done).

For instance:

  >>> a = [1, 2, 3]
 >>> original_a = a
 >>> b = [1, 2, 3]
 >>> original_b = b
 >>> a + = [4]
 >>> b = b + [4]
 >>> a is original_a
 True
 >>> b is original_b
 False

You can see that using += supports the identity of the left side (i.e., a new list is not created) when using + does not support the identifier (i.e. a new list is created).

See http://docs.python.org/library/operator.html#operator.iadd for details and the paragraph directly above the documentation for operator.iadd .

+7
source

In the first case, element = element + [0] you create a new list.

In the second case, the element + = [0], you modify the existing list.

Since the list of lists, a, contains pointers to elements, only changing the elements will actually make a difference. (That is, creating a new list does not change pointers in.)

This can be seen more clearly if we take a simple example showing how the lists work:

 >>> a = [1, 2, 3] >>> b = a >>> a = [4, 5, 6] >>> a [4, 5, 6] >>> b [1, 2, 3] >>> a = [1, 2, 3] >>> b = a >>> a += [4, 5, 6] >>> b [1, 2, 3, 4, 5, 6] >>> a [1, 2, 3, 4, 5, 6] 

Assigning a variable to a list simply assigns a pointer.

+3
source

Adding to what others have said, there is a difference in what these statements do:

 element = element + [0] 

does

 element = element.__add__([0]) 

a

 element += [0] 

does

 element = element.__iadd__([0]) 

__iadd__() , in this case, can freely determine what to return: the original object with a modification or a new object.

In the case of an immutable object, it must return another one (for example, a = b = 8; a += 9 => a is not b .

But in the case of a mutable object, such as a list, it usually modifies this:

 a = b = [] a += [8] 

=> a is b .

This other behavior is reflected in the for loop:

 for element in a: element = element + [0] 

=> name element gets a rebound to another object; the original remains intact

 for element in a: element += [0] 

=> the original object, which is also contained in the external list, a , changes. The fact that element reassigned does not matter; it is not used.

+2
source

Source: https://habr.com/ru/post/903020/


All Articles