1

What does a_list.extend(list2) do (or do better) that a_list += list2 doesn't?

That's all really, except to observe that it would have been an answer if .extend() returned the extended list so you could cascade another method. But it doesn't, so you can't.

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
nigel222
  • 7,582
  • 1
  • 14
  • 22
  • 1
    `+=` was a) added to the language later and b) for lists is implemented as a `list.extend()` call. – Martijn Pieters Aug 17 '16 at 12:55
  • Ah - hadn't thought about the history. Thanks. Am I right to think that `a_list = a_list + list2` would cause a copy of the list to be made, so relatively inefficient? Also why the downvotes? – nigel222 Aug 17 '16 at 12:59
  • 1
    Yes, concatenation creates a new list object. – Martijn Pieters Aug 17 '16 at 13:00
  • 2
    More on these two ways here: http://stackoverflow.com/questions/3653298/concatenating-two-lists-difference-between-and-extend – Dimitris Fasarakis Hilliard Aug 17 '16 at 13:08
  • `a_list = a_list + list2` creates a new list and binds that to the name `a_list`, replacing the original list object. OTOH, `a_list[:] = a_list + list2` copies the new list back to the original list object that's bound to the `a_list` name. This can be useful if other objects hold references to `a_list` and you want them to reflect any changes that you make to `a_list`, however this is a little slower than the simple `a_list = a_list + list2`. – PM 2Ring Aug 17 '16 at 13:12

2 Answers2

11

list.extend() is an expression and can be embedded in larger expressions. += (augmented assignment) is a statement, and statements can never be embedded in expressions.

So you can do this:

doubled_extender = lambda l, it: l.extend(v for v in it for _ in range(2))

but you can't use += there.

Note that for list objects, the object.__iadd__() special method that += uses, calls list.extend() directly before returning self.

Last but not least, the Augmented Assignments feature was added to the language later than list.extend().

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
3

Another benefit of .extend is that you can call it on a global list because that merely mutates the list, whereas += won't work in that context because you can't assign to a global in the local scope.

Demo

a_list = ['one']
list2 = ['two', 'three']

def f():
    a_list.extend(list2)

def g():
    a_list += list2

f()
print(a_list)
g()
print(a_list)

output

['one', 'two', 'three']
Traceback (most recent call last):
  File "./qtest.py", line 43, in <module>
    g()
  File "./qtest.py", line 39, in g
    a_list += list2
UnboundLocalError: local variable 'a_list' referenced before assignment

However, you can use += if you also use slice assignment since that's also a mutation of the original list:

a_list = ['one']
list2 = ['two', 'three']

def g():
    a_list[:] += list2

g()
print(a_list)

output

['one', 'two', 'three']
PM 2Ring
  • 54,345
  • 6
  • 82
  • 182
  • Of course, you can always just add `global a_list` to the function. – chepner Aug 17 '16 at 13:20
  • @chepner Well sure, but I try to avoid using the `global` keyword. Of course, changing globals in any fashion is a dubious practice no matter how you do it, and I suppose using the `global` keyword in your function definition alerts the reader to the fact, which I guess is better than doing it "stealthily" with `.extend` or slice assignment, since "Explicit is better than implicit". – PM 2Ring Aug 17 '16 at 13:23