473,574 Members | 4,964 Online

# Augument assignment versus regular assignment

I do the following. First create lists x,y,z. Then add an element to x
using the augumented assignment operator. This causes all the other
lists to be changed also.
But if I use the assignment x=x+[4] instead of using the augumented
assignment, the y and z lists do not change.
Why is that?
This does not happen when I work with integer data type for example, as
shown below.

Nagy
>>x=y=z=[]
x+=[2]
x
[2]
>>y
[2]
>>z
[2]
>>x=x+[4]

x
[2, 4]
>>y
[2]
>>z
[2]
>>a=b=4
b
4
>>a+=2
a
6
>>b
4

Jul 8 '06 #1
35 2428
nagy wrote:
I do the following. First create lists x,y,z. Then add an element to x
using the augumented assignment operator. This causes all the other
lists to be changed also.
But if I use the assignment x=x+[4] instead of using the augumented
assignment, the y and z lists do not change.
Why is that?
This does not happen when I work with integer data type for example, as
shown below.

Nagy

>>>>x=y=z=[]
In this example, the '[]' creates a new list object. x, y, and z are all
set to reference that object.
>>>>x+=[2]
This does an "in-place" operation on that list, modifying (or
"mutating") the object directly.
>>>>x
[2]
>>>>y

[2]
>>>>z

[2]
>>>>x=x+[4]
This creates a new list that is the concatenation of the list created
above (the list [2]) with a new list (the list [4]). This brand new list
is bound to the name 'x'. The names 'y' and 'z' are left unchanged. That
is, they still point to the original list.
>>>>
x

[2, 4]
>>>>y

[2]
>>>>z

[2]
>>>>a=b=4
This binds the names 'a' and 'b' to the integer object 4.
>>>>b

4
>>>>a+=2
This attempts to mutate the integer object 4, by adding 2 to it.
However, numbers in Python are immutable, and so the in-place operation
fails. Thus, it creates a new integer object equal to 6 (actually,
CPython keeps a cache of certain smaller integer objects and reuses
them, but this does not matter in practice). This new integer object is
bound to the name 'a'. The name 'b' remains bound to the original 4 object.
>>>>a

6
>>>>b

4
Jul 8 '06 #2
Thanks, Kirk.
I considered the += as only a shorthand notation for the assignment
operator.
Since for lists + is simply a concatetation, I am not sure it x=x+[2]
is creating a brand
new list. Could you refer me to any documentation on this?
Thanks,
Nagy
Kirk McDonald wrote:
nagy wrote:
I do the following. First create lists x,y,z. Then add an element to x
using the augumented assignment operator. This causes all the other
lists to be changed also.
But if I use the assignment x=x+[4] instead of using the augumented
assignment, the y and z lists do not change.
Why is that?
This does not happen when I work with integer data type for example, as
shown below.

Nagy

>>>x=y=z=[]

In this example, the '[]' creates a new list object. x, y, and z are all
set to reference that object.
>>>x+=[2]

This does an "in-place" operation on that list, modifying (or
"mutating") the object directly.
>>>x
[2]
>>>y
[2]
>>>z
[2]
>>>x=x+[4]

This creates a new list that is the concatenation of the list created
above (the list [2]) with a new list (the list [4]). This brand new list
is bound to the name 'x'. The names 'y' and 'z' are left unchanged. That
is, they still point to the original list.
>>>
x
[2, 4]
>>>y
[2]
>>>z
[2]
>>>a=b=4

This binds the names 'a' and 'b' to the integer object 4.
>>>b
4
>>>a+=2

This attempts to mutate the integer object 4, by adding 2 to it.
However, numbers in Python are immutable, and so the in-place operation
fails. Thus, it creates a new integer object equal to 6 (actually,
CPython keeps a cache of certain smaller integer objects and reuses
them, but this does not matter in practice). This new integer object is
bound to the name 'a'. The name 'b' remains bound to the original 4 object.
>>>a
6
>>>b
4
Jul 8 '06 #3
nagy wrote:
Thanks, Kirk.
I considered the += as only a shorthand notation for the assignment
operator.
Since for lists + is simply a concatetation, I am not sure it x=x+[2]
is creating a brand
new list. Could you refer me to any documentation on this?
Yes:

http://docs.python.org/ref/augassign.html
"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

This behavior is only logical. Consider:
>>x = [2]
y = x + [4]
After these operations, we have two lists: x (the list [2]) and y (the
list [2, 4]). This is because the expression "x + [4]" creates a new
list. We then bind this new list to the name 'y', and leave the name 'x'
alone.

If we then say this:
>>x = x + [6]
We are doing much the same operation. We are creating a new list (the
list [2, 6]), and binding it to the name 'x'. The list [2], previously
bound to 'x', is no longer bound to anything, so Python frees it.

The augmented assignment, as I went over previously, attempts to modify
the list object directly. Any names bound to the object (or any other
objects that reference the object) will see the changes.

-Kirk McDonald
Jul 8 '06 #4
Looks like x=x+[2] creats a new list to me:
>>b = [8,5,6]
x = b
x = x + [2]
print b,x
[8, 5, 6] [8, 5, 6, 2]

-Chris
On Sat, Jul 08, 2006 at 11:56:11AM -0700, nagy wrote:
Thanks, Kirk.
I considered the += as only a shorthand notation for the assignment
operator.
Since for lists + is simply a concatetation, I am not sure it x=x+[2]
is creating a brand
new list. Could you refer me to any documentation on this?
Thanks,
Nagy
Kirk McDonald wrote:
nagy wrote:
I do the following. First create lists x,y,z. Then add an element to x
using the augumented assignment operator. This causes all the other
lists to be changed also.
But if I use the assignment x=x+[4] instead of using the augumented
assignment, the y and z lists do not change.
Why is that?
This does not happen when I work with integer data type for example, as
shown below.
>
Nagy
>
>
>>>>x=y=z=[]
In this example, the '[]' creates a new list object. x, y, and z are all
set to reference that object.
>>>>x+=[2]
This does an "in-place" operation on that list, modifying (or
"mutating") the object directly.
>>>>x
>
[2]
>
>>>>y
>
[2]
>
>>>>z
>
[2]
>
>>>>x=x+[4]
This creates a new list that is the concatenation of the list created
above (the list [2]) with a new list (the list [4]). This brand new list
is bound to the name 'x'. The names 'y' and 'z' are left unchanged. That
is, they still point to the original list.
>>>>
>>>>x
>
[2, 4]
>
>>>>y
>
[2]
>
>>>>z
>
[2]
>
>>>>a=b=4
This binds the names 'a' and 'b' to the integer object 4.
>>>>b
>
4
>
>>>>a+=2
This attempts to mutate the integer object 4, by adding 2 to it.
However, numbers in Python are immutable, and so the in-place operation
fails. Thus, it creates a new integer object equal to 6 (actually,
CPython keeps a cache of certain smaller integer objects and reuses
them, but this does not matter in practice). This new integer object is
bound to the name 'a'. The name 'b' remains bound to the original 4 object.
>>>>a
>
6
>
>>>>b
>
4
>

--
http://mail.python.org/mailman/listinfo/python-list
Jul 8 '06 #5

nagy wrote:
Thanks, Kirk.
I considered the += as only a shorthand notation for the assignment
operator.
Since for lists + is simply a concatetation, I am not sure it x=x+[2]
is creating a brand
new list. Could you refer me to any documentation on this?
Thanks,
Nagy
My habit is to check the id.
>>x = [1,2]
id(x)
-1209327188
>>x += [4]
x
[1,2,4]
>>id(x)
-1209327188
>>x = x + [6]
x
[1,2,4,6]
>>id(x)
-1209334664

So it looks as if x += [] modifies the list in place, while x = x + []
creates a new list.

I am not sure if this is 100% guaranteed, as I have noticed in the past
that id's can be reused under certain circumstances. Perhaps one of the
resident gurus can comment.

Frank Millman

Jul 9 '06 #6
Frank Millman wrote:
nagy wrote:
>>Thanks, Kirk.
I considered the += as only a shorthand notation for the assignment
operator.
Since for lists + is simply a concatetation, I am not sure it x=x+[2]
is creating a brand
new list. Could you refer me to any documentation on this?
Thanks,
Nagy

My habit is to check the id.

>>>>x = [1,2]
id(x)

-1209327188
>>>>x += [4]
x

[1,2,4]
>>>>id(x)

-1209327188
>>>>x = x + [6]
x

[1,2,4,6]
>>>>id(x)

-1209334664

So it looks as if x += [] modifies the list in place, while x = x + []
creates a new list.

I am not sure if this is 100% guaranteed,
It is. This is true for any mutable type.
as I have noticed in the past
that id's can be reused under certain circumstances. Perhaps one of the
resident gurus can comment.
Jul 9 '06 #7
Frank Millman wrote:
So it looks as if x += [] modifies the list in place, while x = x + []
creates a new list.
objects can override the += operator (by defining the __iadd__ method),
and the list type maps __iadd__ to extend. other containers may treat
+= differently, but in-place behaviour is recommended by the language
reference:

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

</F>

Jul 9 '06 #8
On 2006-07-09, Fredrik Lundh <fr*****@python ware.comwrote:
Frank Millman wrote:
>So it looks as if x += [] modifies the list in place, while x = x + []
creates a new list.

objects can override the += operator (by defining the __iadd__ method),
and the list type maps __iadd__ to extend. other containers may treat
+= differently, but in-place behaviour is recommended by the language
reference:

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
What does it mean that x is only evaluated once. I have an avltree module,
with an interface much like a directory. So I added print statements to
__setitem__ and __getitem__ and then tried the following code.
>>from avltree import Tree
t=Tree()
t['a'] = 1
__setitem__, key = a
>>t['a']
__getitem__, key = a
1
>>t['a'] = t['a'] + 1
__getitem__, key = a
__setitem__, key = a
>>t['a'] += 1
__getitem__, key = a
__setitem__, key = a
>>t['b'] = []
__setitem__, key = b
>>t['b'] = t['b'] + [1]
__getitem__, key = b
__setitem__, key = b
>>t['b'] += [2]
__getitem__, key = b
__setitem__, key = b

So to me it seems that when we substitute t['a'] or t['b'] for x,
x is evaluated twice with the augmented version, just like it
is with the not augmented version.

--
Antoon Pardon

Jul 10 '06 #9
In article <sl************ ********@rcpc42 .vub.ac.be>,
Antoon Pardon <ap*****@forel. vub.ac.bewrote:
>On 2006-07-09, Fredrik Lundh <fr*****@python ware.comwrote:
>Frank Millman wrote:
>>So it looks as if x += [] modifies the list in place, while x = x + []
creates a new list.

objects can override the += operator (by defining the __iadd__ method),
and the list type maps __iadd__ to extend. other containers may treat
+= differently, but in-place behaviour is recommended by the language
reference:

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

What does it mean that x is only evaluated once. I have an avltree module,
with an interface much like a directory. So I added print statements to
__setitem__ and __getitem__ and then tried the following code.
>>>from avltree import Tree
t=Tree()
t['a'] = 1
__setitem__, key = a
>>>t['a']
__getitem__, key = a
1
>>>t['a'] = t['a'] + 1
__getitem__, key = a
__setitem__, key = a
>>>t['a'] += 1
__getitem__, key = a
__setitem__, key = a
>>>t['b'] = []
__setitem__, key = b
>>>t['b'] = t['b'] + [1]
__getitem__, key = b
__setitem__, key = b
>>>t['b'] += [2]
__getitem__, key = b
__setitem__, key = b

So to me it seems that when we substitute t['a'] or t['b'] for x,
x is evaluated twice with the augmented version, just like it
is with the not augmented version.
\$ cat x.py

def getindex(ind = 0):
print 'getindex() called'
return ind

a = [0, 1, 2, 3, 4, 5]
a[getindex(0)] = a[getindex(0)] + 17
print a
a[getindex(1)] += 22
print a

\$ python x.py
getindex() called
getindex() called
[17, 1, 2, 3, 4, 5]
getindex() called
[17, 23, 2, 3, 4, 5]

In this case, getindex() is a rather pointless function, but it could
be an expensive one or one with side effects or even one which alters
state, so that it gives different values on subsequent calls with the
same argument.

The += version finds the object to be operated upon once, the expanded
version does it twice.
--
Jim Segrave (je*@jes-2.demon.nl)

Jul 10 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.