16
I was seeing, there are people who speak that is different and there are those who speak that is the same thing. I am confused. They are different or do the same thing?
16
I was seeing, there are people who speak that is different and there are those who speak that is the same thing. I am confused. They are different or do the same thing?
16
As already commented, there will be no difference in the result.
But we will do a simple debugging of your code:
from dis import dis
code = '''
i=1
i+=2
'''
print(dis(code))
2 0 LOAD_CONST 0 (1)
3 STORE_NAME 0 (i)
3 6 LOAD_NAME 0 (i)
9 LOAD_CONST 1 (2)
12 INPLACE_ADD
13 STORE_NAME 0 (i)
16 LOAD_CONST 2 (None)
19 RETURN_VALUE
None
from dis import dis
code = '''
i=1
i=i+2
'''
print(dis(code))
2 0 LOAD_CONST 0 (1)
3 STORE_NAME 0 (i)
3 6 LOAD_NAME 0 (i)
9 LOAD_CONST 1 (2)
12 BINARY_ADD
13 STORE_NAME 0 (i)
16 LOAD_CONST 2 (None)
19 RETURN_VALUE
None
Note that the only difference is between the instructions INPLACE_ADD
and BINARY_ADD
Translating, via google Translate, the question:
When is "i += x" Different from "i = i + x" in Python?
When it is "i + = x" other than "i = i + x" in Python?
We’ll get to this reply, translated via google Translate:
It depends entirely on the object
i
.
+=
calls the __iadd__method (if it exists - running__add__
if not exist) as long as+
calls the __add__method¹ or the __radd__method in some cases¹ .From an API perspective,
__iadd__
is supposed to be used for modify mutable objects in place (returning the object that was mutated), while__add__
must return a new instance of something. For objects immutable , the two methods return a new instance, but__iadd__
will place the new instance in the current namespace with the same name as the old instance. That’s whyi = 1 i += 1
seems to increase
i
. In reality, you get a new integer and the attributes "on top of"i
-- missing a reference to the integer former. In that case,i += 1
is exactly the same asi = i + 1
.But with most changeable objects, it’s a different story:
As a concrete example:
a = [1, 2, 3] b = a b += [1, 2, 3] print a #[1, 2, 3, 1, 2, 3] print b #[1, 2, 3, 1, 2, 3]
compared to:
a = [1, 2, 3] b = a b = b + [1, 2, 3] print a #[1, 2, 3] print b #[1, 2, 3, 1, 2, 3]
note how in the first example, once
b
anda
refer to the same object, when use+=
inb
, he really changesb
(anda
see the change also - After all, it is referencinga
in the same list).In the second case, however, when I do
b = b + [1, 2, 3
], that takes the list thatb
is making reference anda
concatenates with a new list[1, 2, 3]
. It then stores the concatenated list in the current namespace asb
-- without considering whatb
was the line previous.¹ In the expression
x + y
, ifx.__add__
is not implemented orx.__add__(y)
returnsNotImplemented
andx
andy
have guys different , next,x + y
tries to call y.Radd(x). So in case you havefoo_instance += bar_instance
if
Foo
not implement__add__
or__iadd__
then the result here is the same asfoo_instance = bar_instance.__radd__(bar_instance, foo_instance)
² In the expression
foo_instance + bar_instance
,bar_instance.__radd__
will be tried beforefoo_instance.__add__
if the type ofbar_instance
is a subclass of thefoo_instance(eg issubclass(Bar, Foo))
. The rationale for this is becauseBar
is in certain a "high level" object thatFoo
thusBar
must obtain the option to replace the behavior ofFoo
.
9
I found something interesting on the PEP-203 which is where they propose the Augmented assignment (i += 2):
The idea behind the increased assignment in Python is that it’s not just an easier way to write the common practice of storing the result of a binary operation in your left operand, but also a way for the operative of the left in question to know that it must operate on itself, instead of creating a modified copy of itself.
Source: https://www.python.org/dev/peps/pep-0203/#id8
In my conclusion, an important difference is that in the increased assignment it might not create a modified copy of itself, for optimization purposes.
Your summary conclusion is not correct, and can be dangerous. For immutable objects - which includes Python numeric types, the increased assignment creates a new object likewise. For mutable objects, such as lists, and then dictionaries (the operation of "+" with dictionaries was accepted for Python 3.9), this assignment modifies the object prodio.
Edited! Thanks for the comment!
Edited the response to reflect the fact that += can avoid the creation of an object, does not mean that going avoid (or which must be avoided).
@epx yes, but this is not valid for strings as you suggested in your reply.
https://www.codementor.io/satwikkansal/do-you-really-think-you-know-strings-in-python-fnxh8mtha suggests that it is valid yes.
@epx In which part?
-1
In the case of a number there is not much difference, but if it was a more complex type, it may be that += would be more efficient than + because it does not need to create a new object.
For example, suppose it is the type String,
a = a + b
in fact what happens behind the scenes is:
tmp = a + b
a = tmp
The string "tmp" is completely new, and for a brief period coexists with "a" in memory.
Already the expression
a += b
can be optimized to work directly on the "entrails" of the string "a" in order to attach the contents of "b", as it is clear that the original value of "a" does not matter anymore.
Even though the string is an immutable type in Python and many other languages, this is a case where it can be changeable internally.
I cited the type string only as an example, it may or may not take advantage of this difference between operators. The fact is that Python allows you to do this type of optimization by implementing your type or class, implementing the __iadd__ method beyond __add__, assuming of course that the "add" operation makes sense to it.
How is it possible to get a changeable string internally? I don’t understand this part.
That is there within the implementation; for human consumption it is immutable.
In Java has some Stringio type deals that play role of mutable string, must have something similar to Pyhthon.
Do you have sources to back up this information? I’ve been over and over the Python C source and I don’t remember ever seeing references to that possible Python changeability string, nor how this could influence the difference in the call of operators.
I said that an implementation CAN optimize by discriminating between operators += and +. If Python (or the Python C implementation; has pypy, has Ironpython, has others) does this, it is outside the scope of the question.
Besides, I used the native String type as an example. You can create a new type, or a class, and implement __iadd__ optimally in relation to __add__.
Well, then I’ll keep the negative; if the question is "how does it work in Python", I don’t see how useful an answer like "I don’t know what it’s like in Python, but it could be like this..."
This conclusion is wrong and the test is simple to just manipulate the references for a string: 1) create a string called a
: >>> a = "teste"
. 2) It is done b
a reference to a
: >>> b = a
. 3) If +=
modifies the string’s internal structure by not creating a new object, so we conclude that if we do >>> a += " mais"
, a
and b
will continue to reference the same object and both >>> print(a)
and >>> print(b)
print the same result. 4) Conclusion >>> print(a)
printed teste mais
and >>> print(b)
printed teste
implying that >>> a += " mais"
created a new object in a
.
String in Python is an immutable type. Your test does not prove that optimization is not done. Any decent String implementation implements internal reference count and copy-on-write. The only thing your test proves is that the implementation is ok, which is not exactly a novelty.
I found this article: https://www.codementor.io/satwikkansal/do-you-really-think-you-know-strings-in-python-fnxh8mtha snippet: += is Actually Faster than + for concatenating more than two strings because the first string (example, S1 for S1 += s2 + S3) is not destroyed while calculating the complete string.
-4
There is no difference as to the results, only in the writing mode, one being more summarized and the other not. Thus, both can be used, as there will be no change in any results.
Monteiro, I invite you to read Luiz Augusto’s answer: https://answall.com/a/402702/5878
Browser other questions tagged python python-3.x variables
You are not signed in. Login or sign up in order to post.
No difference in result. The first form is only more compact.
– anonimo
The first calls the method
__iadd__
; the second method__add__
. The result produced is the same for integer if none of these methods is overwritten.– Woss
The only thing I’ve ever heard is that the auto increment metod is faster by not having to allocate twice the space in memory, apart from that there is no difference and maybe its impact on peformance is not so great depending on the size of the processing
– Marcos Brinner
I did both and gave different results in two lists. The first way:
a = [1, 2, 3]
b = a
b += [1, 2, 3]
print(a) # [1, 2, 3, 1, 2, 3]
print(b) # [1, 2, 3, 1, 2, 3]
The second way: a = [1, 2, 3] b = a b = b + [1, 2, 3] print(a) # [1, 2, 3] print(b) # [1, 2, 3, 1, 2, 3]– Cavernosa Spider