简体   繁体   中英

+= in Python when assigning it to third variable

When I was looking at meaning of the += operator in Python, I looked at the answers to a similar question: What exactly does += do in python? . But in the below code excerpt:

increments += arr[i-1] - arr[i]

There is a third variable used. If I understood the concept it subtracts arr[i] from arr[i-1] and adds it to increments 's value and the result is assigned to increments . To elaborate: is the above statement similar to

increments = increments + (arr[i-1] - arr[i])

or is there more to it?

From the documentation :

An augmented assignment evaluates the target (which, unlike normal assignment statements, cannot be an unpacking) and the expression list, performs the binary operation specific to the type of assignment on the two operands, and assigns the result to the original target. The target is only evaluated once.

An augmented assignment expression like x += 1 can be rewritten as x = x + 1 to achieve a similar, but not exactly equal effect. In the augmented version, x is only evaluated once. Also, when possible, the actual operation is performed in-place, meaning that rather than creating a new object and assigning that to the target, the old object is modified instead.

Unlike normal assignments, augmented assignments evaluate the left-hand side before evaluating the right-hand side. For example, a[i] += f(x) first looks-up a[i] , then it evaluates f(x) and performs the addition, and lastly, it writes the result back to a[i] .

With the exception of assigning to tuples and multiple targets in a single statement, the assignment done by augmented assignment statements is handled the same way as normal assignments. Similarly, with the exception of the possible in-place behavior, the binary operation performed by augmented assignment is the same as the normal binary operations.

For targets which are attribute references, the same caveat about class and instance attributes applies as for regular assignments.

(my emphasis in the second paragraph)

So yes, there's more to it than just increments = increments + (arr[i-1] - arr[i]) . The degree to which it matters depends on what you're applying the operator to.

To elaborate: is the above statement similar to

increments = increments + (arr[i-1] - arr[i])

That depends on the type of "increments".

With regards to the core built-in types (and other types that try to follow the pattern set by them) there are two at least two notable differences between + and +=.

  1. Where the type is mutable += performs the modification in-place while + creates a new object.
  2. For lists += is more flexible than +, + will only accept another list but += will accept any iterable.

Numbers are immutable, so for numbers the two statements behave the same. However it is interesting to see if we can figure out some cases where they do behave differently.

We are quite limited in what types we can use because relatively few types support both "+" and "-" and most types only support operations with the same type. A combination of making increments a list and making the elements of arr sets is one way to demonstrate a difference.

increments=[]
i = 1 
arr=[{"foo","bar"},{"bar","baz"}]
increments += arr[i-1] - arr[i]
print(increments)

"Prints ['foo']"

increments=[]
i = 1 
arr=[{"foo","bar"},{"bar","baz"}]
increments = increments + (arr[i-1] - arr[i])
print(increments)

Raises an exception "TypeError: can only concatenate list (not "set") to list"

But that is a rather contrived example, for something more realistic we want a type that is mutable and supports both "+" and "-". I don't think there are any such types among the core built-in types but one widely used type that does is the "array" type from numpy.

from numpy import array
increments=array((1,2))
oldincrements=increments
i = 1 
arr=[array((3,4)),array((5,6))]
increments += arr[i-1] - arr[i]
print(repr(oldincrements)+' '+repr(increments))

Prints "array([-1, 0]) array([-1, 0])". The numpy array was modified in-place so both "oldincrements" and "increments" were affected.

from numpy import array
increments=array((1,2))
oldincrements=increments
i = 1 
arr=[array((3,4)),array((5,6))]
increments = increments + (arr[i-1] - arr[i])
print(repr(oldincrements)+' '+repr(increments))

Prints "array([1, 2]) array([-1, 0])" the array pointed to by increments was not modified in-place, instead a new array was created and assigned to "increments". So "oldincrements" was not affected.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM