7

Can someone please explain this behaviour :

>>> a = {'hello':'world' , 'good':'food'}
>>> b = [1,2]
>>> b = b + a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate list (not "dict") to list
>>> b += a
>>> b
[1, 2, 'good', 'hello'] <--- Why do the keys get added when dict cannot be added to a list
>>> 
DhruvPathak
  • 42,059
  • 16
  • 116
  • 175
  • 9
    `listobj += something` is the same as `listobj.extend(something)` and the latter takes any iterable. `list(dict)` is a list of the keys. – Martijn Pieters Oct 16 '13 at 09:17
  • 1
    @MartijnPieters: Sure, but that doesn't explain *why* `dict` is disallowed from being explicitly added to a `list`. – Ignacio Vazquez-Abrams Oct 16 '13 at 09:18
  • @IgnacioVazquez-Abrams: Yes, it does. `listobj +=` and `list +` are *not* the same thing. – Martijn Pieters Oct 16 '13 at 09:19
  • 1
    @IgnacioVazquez-Abrams Yes it does. The first example is adding a dictionary to a list. The second example is adding a dictionaries' keys to a list. It works the second time round because it's getting the keys of the dictionary and not the actual dictionary – TerryA Oct 16 '13 at 09:20
  • 1
    @IgnacioVazquez-Abrams: The dupe I linked to is itself a dupe, but the final target doesn't explain that `list.__iadd__` is a proxy for `list.extend()`. – Martijn Pieters Oct 16 '13 at 09:20
  • @Haidro: The `dict` is being passed in both cases to the appropriate method. – Ignacio Vazquez-Abrams Oct 16 '13 at 09:21
  • @MartijnPieters That they can be different things doesn't explain why list chooses to do different things in both cases (i.e. why it doesn't accept arbitrary iterables for `+`). However, that's a different question (and has been asked before, IIRC). –  Oct 16 '13 at 09:21
  • Related: [When is “i += x” different from “i = i + x” in Python?](http://stackoverflow.com/questions/15376509/when-is-i-x-different-from-i-i-x-in-python) – Ashwini Chaudhary Oct 16 '13 at 09:21
  • @delnan: It has been asked before, and I *think* I can find it again. – Martijn Pieters Oct 16 '13 at 09:22
  • 1
    @MartijnPieters It's http://stackoverflow.com/q/13905008/395760 but I'd like confirmation from OP before closing *this* question as duplicate of that. –  Oct 16 '13 at 09:23
  • **Much** better dupe targets: [List extending strange behaviour](http://stackoverflow.com/q/13904039), [Different behaviour for list.\_\_iadd\_\_ and list.\_\_add\_\_](http://stackoverflow.com/q/9766387) and [Why does adding to a list do different things?](http://stackoverflow.com/q/10149568) – Martijn Pieters Oct 16 '13 at 09:24
  • @delnan I would agree it is nearly asking the same thing as the mentioned question. Please mark it as closed . – DhruvPathak Oct 16 '13 at 09:30

1 Answers1

5

Because a = a + b and a += b are not the same thing. The former calls __add__1 (and does regular assignment, which cannot be overloaded), while += calls __iadd__ (and also does regular assignment, but only to allow falling back to __add__ when __iadd__ is not implemented). Lists define both with different semantics; __add__ creates a new list and requires both operands to be lists, while __iadd__ is essentially .extend() and hence (1) works on any iterable and (2) mutates the list in-place.

1 Or __radd__ in some cases, but I'm glossing over that because it doesn't really affect the outcome in this case.

  • 3
    "Don't ask why it was decided to do things that way." That's exactly what he's doing. – Ignacio Vazquez-Abrams Oct 16 '13 at 09:20
  • @IgnacioVazquez-Abrams In that case, it's a duplicate of a different question, see my discussion with Martijn Pieters in the question comments. But I don't read the question that way yet, OP is free to clarify. –  Oct 16 '13 at 09:25