1

I have a list like this:

numlist = [1,2,3]

But, I know I can't do this: numlist += 1.

Because it will raise a TypeError: 'int' object is not iterable.

And I have to do numlist += 1, So it will make a tuple.

But then why?:

>>> numlist = [1,2,3]
>>> numlist += 1,
>>> numlist
[1, 2, 3, 1]

Doesn't give errors.

My question

I did it with a variable, but if I do:

[1,2,3] + 1,

I get

TypeError: can only concatenate list (not "int") to list

Why if I do list + 1, then errors but if I do variablecontainslist += 1, then no errors?

And also,

[1,2,3] + (1,)

Gives

TypeError: can only concatenate list (not "tuple") to list
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
ppwater
  • 2,315
  • 4
  • 15
  • 29
  • 2
    This is just because `+` has higher precedence than `,` but `+=` has lower precedence. – kaya3 Jan 03 '21 at 05:07
  • What do you mean? – ppwater Jan 03 '21 at 05:07
  • @kaya3: That's one of the things going wrong, but even if you added parentheses, it still wouldn't work. – user2357112 Jan 03 '21 at 05:08
  • Compare e.g. `x = 1` and then `x *= 4 + 5` or `x * 4 + 5`. In the `*=` one it will do `4 + 5` before multiplying, in the other one it will do `x * 4` before adding. – kaya3 Jan 03 '21 at 05:08
  • @kaya3 Yes, then how in this situation? There is errors if I add parentheses – ppwater Jan 03 '21 at 05:09
  • 3
    That's because then you are trying to add/concatenate a tuple to a list, which is not allowed. – Jarvis Jan 03 '21 at 05:11
  • Ah, okay. So it's because of the precedence, but if I add parentheses then it gets a tuple, and I add/concatenate a tuple to a list, Which is not allowed... – ppwater Jan 03 '21 at 05:14
  • If anyone answers, I'll be glad to accept it. – ppwater Jan 03 '21 at 05:15
  • It has already been responded here https://stackoverflow.com/questions/13905008/why-must-python-list-addition-be-homogenous – Rysicin Jan 03 '21 at 05:30
  • 2
    Also, from the docs: "for lists, __iadd__ is equivalent to calling extend on the list and returning the list. That’s why we say that for lists, += is a 'shorthand' for list.extend" – Rysicin Jan 03 '21 at 05:34
  • Ah, okay. Thanks for the info. – ppwater Jan 03 '21 at 05:35
  • 2
    And to finish @Rysicin thought - `.extend` accepts any iterable, not just other lists. – SethMMorton Jan 03 '21 at 05:36
  • 2
    @ppwater I’d just like to note that all the discussion about precedence is not relevant, but you probably gathered that already. – SethMMorton Jan 03 '21 at 05:55

2 Answers2

3

Just Try this:

x = []                 # empty list
x += "hello"           # iterates over the string and appends to list
print(x)               # ['h', 'e', 'l', 'l', 'o']

versus

x = []                 # empty list
x = x + "hello"        # TypeError: can only concatenate list (not "str") to list

The += operator invokes the __ iadd__() list method, while + one invokes the __ add__() one. They do different things with lists. += adds a number to a variable, changing the variable itself in the process (whereas + would not).

2

There is a lack of symmetry here. When using a list, x += y is basically x.extend(y) and extend works with any iterable.

extend(self, iterable, /)
    Extend list by appending elements from the iterable.

But x = x + y is more restrictive. If x is a list, y must be a list also. The list.__add__ method knows the size and structure of both objects, so it can create the new list efficiently. I'm not sure why the implementers didn't keep these same restrictions for augmented addition. But its easy to turn __iadd__ into an extend and the functionality is cool.

As for [1,2,3] + 1,, this expression creates a tuple but it fails on the first element. Had this been an operation that doesn't fail, you'd get the tuple.

>>> [1,2,3] + [4],
([1, 2, 3, 4],)
tdelaney
  • 73,364
  • 6
  • 83
  • 116