13
>>> b = []
>>> c = '1234'
>>> b += c
>>> b
['1', '2', '3', '4']
>>> 

What is happening here? This should not work, right? Or am I missing something obvious?

>>> b = []
>>> c = '1234'
>>> b + c
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    b + c
TypeError: can only concatenate list (not "str") to list
>>> 

Then a += b is not always equivalent to a = a + b ?

3
  • 1
    Is this behaviour still present in Python 3.x? I always found it irritating that a standard library type breaks the general contract that a += b <=> a = a + b (without affecting any other references to the original a value). Commented Nov 30, 2011 at 9:01
  • 2
    @Karl Knechtel: unfortunately, it's still present in Python 3.2.1. Commented Nov 30, 2011 at 9:16
  • I was checking it in python 3.2, yes. I found the issue looking at a beginner code that was producing wrong results. I could not find any reference to this specific behavior in Learning Python. I checked PEP203 and it says that __iadd__ is used but also they say that __iadd__ is the inplace __add__ that is not the case in this case... Maybe someone could explain the rational beneath this behavior or point/link to some discussion about that? I understand from Karl's comment that there is people concerned about it Commented Nov 30, 2011 at 10:28

7 Answers 7

18

Strings are iterable: the elements are the string's characters. When you add an iterable to a list, the iterable's elements get appended to the list.

Either of the following will do what you're expecting (i.e. append the string, not extend the list with the string's characters):

b += [c]

or

b.append(c)
Sign up to request clarification or add additional context in comments.

Comments

11

The += operator extends a list instead of appending to it:

>>> b = []
>>> c = "1234"
>>> b.append(c)
>>> b
['1234']
>>> b.extend(c)
>>> b
['1234', '1', '2', '3', '4']
>>> b += c
>>> b
['1234', '1', '2', '3', '4', '1', '2', '3', '4']
>>> b += [c]
>>> b
['1234', '1', '2', '3', '4', '1', '2', '3', '4', '1234']

2 Comments

do you know a source of documentation on the effect of these operators (+, +=) for iterables/sequences/... ?
@moooeeeep - in the table in the docs - you can also see how it happens in the actual source.
4

This is an answer not to the original question (which I think has been adequately answered), but to the numerous questions that have been asked in the comments about the semantics of augmented assignment (+= and similar operations).

In a nutshell: Augmented assignment works differently for mutable types than for immutable ones.

str, tuple, and the numeric types, among others, are immutable. The contents of a tuple cannot be changed once it has been created, so you get this behavior:

>>> a = (1, 2)
>>> b = a
>>> a += (3, 4)
>>> a
(1, 2, 3, 4)
>>> b
(1, 2)

str has the same semantics. Basically, a += b is equivalent to a = a + b if a is immutable.

Most other types, including list, are mutable. A list's contents can be changed in place, and augmented assignment does exactly that. Hence:

>>> a = [1, 2]
>>> b = a
>>> a += [3, 4]
>>> a
[1, 2, 3, 4]
>>> b
[1, 2, 3, 4]

Whereas if the third line were replaced with a = a + [3, 4], a new list would be created and b would be [1, 2].

For a user-defined class, the semantics depend on how it was implemented, but this is how it's supposed to be done per PEP 203.

1 Comment

This is a really good observation. a and b share the same memory address until a is evaluated on the left hand side of an assignment operator? Could you include that?
2

A string is a sequence of characters. The list operation += takes any sequence and appends each of the sequence's elements to the list.

(Actually += takes any iterable.)

3 Comments

+ is a different operator than +=.
I know, it is called augmented assigment and it is defined to be equivalent to a = a + b (see PEP203). Taking this definition strictly drive me to a wrong expectation. That is what surprised me (probably I never dared to add a list to a string in my python code so I never collided with this before). Should not be In the face of ambiguity, refuse the temptation to guess ?.
Nowhere in PEP-203 does it claim that a += b is equivalent to a = a + b.
2

+= is syntactic sugar for extend, but + is just list concatenation. If you extend, you'll iterate over the argument, which in this case is a string. But you can't concatenate a string to a list, hence + fails.

Comments

0

What did you expect? If you want to add c as string you must to do:

b.append(c)

Cheers!

2 Comments

But as Tim explained above the behavior of += is not the same that +
please, see comment on Tim post.
0

In essence, the += operator on the list will retrieve c's iterator, which will yield the individual characters in order. If you intended to add the actual string to the list, yielding the result ['1234'], you can use b.append('1234') instead.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.