a=([],); a[0]+=[1]

  • Thread starter Andrea Griffini
  • Start date
A

Andrea Griffini

When reading about python "warts" i stepped in this
example I find quite puzzling:

a = ( [] , )
a[0] += [1]

this gives an error, because a tuple cannot be
modified. But if you print the content of "a"
it will show it has indeed been modified.

How can this happen ? if "+=" for list was called
then no modification to the tuple was requested and
so no error should have been raised; if instead "+"
and "=" was executed then after a failing assignment
the original list is safe... (or at least I thought
so; if you type "a[0] = [2]" you get the error and
"a" is not modified).

Is there an explanation simpler than investigating
on python sources ?

Andrea
 
D

Duncan Booth

When reading about python "warts" i stepped in this
example I find quite puzzling:

a = ( [] , )
a[0] += [1]

this gives an error, because a tuple cannot be
modified. But if you print the content of "a"
it will show it has indeed been modified.

How can this happen ? if "+=" for list was called
then no modification to the tuple was requested and
so no error should have been raised; if instead "+"
and "=" was executed then after a failing assignment
the original list is safe... (or at least I thought
so; if you type "a[0] = [2]" you get the error and
"a" is not modified).

Is there an explanation simpler than investigating
on python sources ?

+= is implemented by calling the __iadd__ method (if it exists, otherwise
__add__ is called). In either case the result of the method is then
assigned to the destination.

So what is happening here is that list.__iadd__ modifies the list in place,
but then the attempt to assign the result into the tuple fails.

Although __iadd__ extends the list in place this need not be true for all
types. An object could have an implementation for inplace addition that
actually creates a new object, so Python cannot optimise out the store.

See http://groups.google.co.uk/[email protected]
for a (long) discussion of this topic.
 
M

Mark 'Kamikaze' Hughes

Andrea Griffini said:
When reading about python "warts" i stepped in this
example I find quite puzzling:
a = ( [] , )
a[0] += [1]
this gives an error, because a tuple cannot be
modified. But if you print the content of "a"
it will show it has indeed been modified.
How can this happen ? if "+=" for list was called
then no modification to the tuple was requested and
so no error should have been raised; if instead "+"
and "=" was executed then after a failing assignment
the original list is safe... (or at least I thought
so; if you type "a[0] = [2]" you get the error and
"a" is not modified).
Is there an explanation simpler than investigating
on python sources ?

First, as a matter of principle you probably shouldn't be modifying
the contents of a tuple, even if those contents are mutable.

What you're seeing is that += is shorthand for "add, then store back
in the original container". So it appends to the mutable list, then
tries to store that list back in the tuple, which fails. Here's an
alternative:

Python 2.3.3 (#1, Mar 10 2004, 15:56:38)
[GCC 3.3.1 (SuSE Linux)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
a=([],)
a ([],)
a[0] []
a[0].append(1)
a
([1],)

But see "First" above, and don't do this. If you want the outer list
to be mutable, use a mutable list instead of a tuple.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,197
Messages
2,571,038
Members
47,633
Latest member
BriannaLyk

Latest Threads

Top