Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python assignment operator differs from non assignment

Tags:

I have face this weird behavior I can not find explications about.

MWE:

l = [1]
l += {'a': 2}
l
[1, 'a']
l + {'B': 3}
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: can only concatenate list (not "dict") to list

Basically, when I += python does not raise an error and append the key to the list while when I only compute the + I get the expected TypeError.

Note: this is Python 3.6.10

like image 884
ClementWalter Avatar asked Apr 27 '20 10:04

ClementWalter


People also ask

What are assignment operators in Python?

Assignment operators in Python are in-fix which are used to perform operations on variables or operands and assign values to the operand on the left side of the operator. It performs arithmetic, logical, and bitwise computations.


2 Answers

l += ... is actually calling object.__iadd__(self, other) and modifies the object in-place when l is mutable

The reason (as @DeepSpace explains in his comment) is that when you do l += {'a': 2} the operation updates l in place only and only if l is mutable. On the other hand, the operation l + {'a': 2} is not done in place resulting into list + dictionary -> TypeError.


(see here)


l = [1]
l = l.__iadd__({'a': 2})
l
#[1, 'a']

is not the same as + that calls object.__add__(self, other)

l + {'B': 3}
TypeError: can only concatenate list (not "dict") to list
like image 130
seralouk Avatar answered Oct 18 '22 15:10

seralouk


So as the authors say this is not a bug. When you Do a += b it is like b come to a's house and changing it the way that a like it to be. what the Authors say is when you do a + b it cannot be decided which one's style will get prioritized. and no one knows where will the result of a + b will go until you execute it. So you can't decide whose style it would be. if it is a style it would be [1, 'a']'s, and if it is b style it would be an error. and therefore it cannot be decided who will get the priority. So I don't personally agree with that statement. because when you take the call stack a is in a higher place than b. when there is a expression like a + b you first call a.__add__(self, other) if a.__add__ is NotImplemented (in this case it is implemented). then you call a.__radd__(self, other). which means call other.__add__ in this case b.__add__. I am telling this based on the place of the call stack and the python community may have more important reasons to do this.

like image 21
Hyperx837 Avatar answered Oct 18 '22 13:10

Hyperx837