List comprehension and in place methods [duplicate] - python

This question already has answers here:
Why do these list operations (methods: clear / extend / reverse / append / sort / remove) return None, rather than the resulting list?
(6 answers)
Alternatives to using in-place list methods within a list comprehension?
(3 answers)
Closed 6 months ago.
I am just trying to understand what happens during list comprehension. Some methods which work on lists 'in-place' don't seem to work when applied in a list comprehension:
a = [[1, 2, 3], [4, 5, 6]]
i1 = id(a[0])
for i in a: i.reverse()
>>> [[3, 2, 1], [6, 5, 4] # Works
print i1 == id(a[0]) # True, same memory address
a = [i.reverse() for i in a]
>>> [None, None] # Doesn't work
print i1 == id(a[0]) # False, new memory address
a = [i[::-1] for i in a]
>>> [[3, 2, 1], [6, 5, 4]] # Works!
print i1 == id(a[0]) # False
I am guessing this has something to do with all the elements getting copied to a different memory space. Why does i[::-1] work whereas i.reverse() doesn't?

i.reverse() reverses the array in place and doesn't return anything, meaning it returns None type. That way you obtain [None, None] from list comprehension and previous arrays' elements are reversed at the same time.
These two shouldn't be mixed, either use a for and x.reverse(), or use reversed(x) or x[::-1] in a list comprehension.

i.reverse() reverses the list in-place and returns None.
What the docs say:
list.reverse()
Reverse the elements of the list, in place
vs.
reversed(seq)
Return a reverse iterator. seq must be an object which has a
__reversed__() method or supports the sequence protocol
(the __len__() method and the __getitem__() method with integer arguments starting at 0).
Examples:
>>> xs = [1, 2, 3]
>>> id(xs)
140625121860208
>>> ys = xs[::-1]
>>> id(ys)
140625121924088
Slicing creates a new list.
>>> xs.reverse()
>>> xs
[3, 2, 1]
>>> id(xs)
140625121860208
In-place sorting/reversing retains the original list.
>>> zs = list(reversed(xs))
>>> zs
[1, 2, 3]
>>> id(zs)
140625121976400
reversed() returns an iterator; which when turns into a list creates a new list! If you have a read of PEP 0322 -- Reverse Iteration you'll note that reversed() does not create a new data structure but simply iteratoes over the sequence in reverse order.

This does what you intend:
>>> a = [[1, 2, 3], [4, 5, 6]]
>>> [list(reversed(i)) for i in a]
[[3, 2, 1], [6, 5, 4]]
List comprehension always returns a new list, so using the in-place reverse
method just returns the return value of reverse, which is None.
The function reversed() gives you an new iterator. Converting it to
a list is for your example the same as:
>>> [i[::-1] for i in a]
Even though they look very similar, it is important to distinguish both,
the function reversed() and the method obj.reverse()

list.reverse reverses a list in place, and return None.
while slice a[::-1] creates another list and return as value.
list comprehension will take the return value of each expression.

Related

How to insert a value into a list without it being a list inside a list [duplicate]

This question's answers are a community effort. Edit existing answers to improve this post. It is not currently accepting new answers or interactions.
What's the difference between the list methods append() and extend()?
append appends a specified object at the end of the list:
>>> x = [1, 2, 3]
>>> x.append([4, 5])
>>> print(x)
[1, 2, 3, [4, 5]]
extend extends the list by appending elements from the specified iterable:
>>> x = [1, 2, 3]
>>> x.extend([4, 5])
>>> print(x)
[1, 2, 3, 4, 5]
append adds an element to a list. extend concatenates the first list with another list/iterable.
>>> xs = ['A', 'B']
>>> xs
['A', 'B']
>>> xs.append("D")
>>> xs
['A', 'B', 'D']
>>> xs.append(["E", "F"])
>>> xs
['A', 'B', 'D', ['E', 'F']]
>>> xs.insert(2, "C")
>>> xs
['A', 'B', 'C', 'D', ['E', 'F']]
>>> xs.extend(["G", "H"])
>>> xs
['A', 'B', 'C', 'D', ['E', 'F'], 'G', 'H']
What is the difference between the list methods append and extend?
append adds its argument as a single element to the end of a list. The length of the list itself will increase by one.
extend iterates over its argument adding each element to the list, extending the list. The length of the list will increase by however many elements were in the iterable argument.
append
The list.append method appends an object to the end of the list.
my_list.append(object)
Whatever the object is, whether a number, a string, another list, or something else, it gets added onto the end of my_list as a single entry on the list.
>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
So keep in mind that a list is an object. If you append another list onto a list, the first list will be a single object at the end of the list (which may not be what you want):
>>> another_list = [1, 2, 3]
>>> my_list.append(another_list)
>>> my_list
['foo', 'bar', 'baz', [1, 2, 3]]
#^^^^^^^^^--- single item at the end of the list.
extend
The list.extend method extends a list by appending elements from an iterable:
my_list.extend(iterable)
So with extend, each element of the iterable gets appended onto the list. For example:
>>> my_list
['foo', 'bar']
>>> another_list = [1, 2, 3]
>>> my_list.extend(another_list)
>>> my_list
['foo', 'bar', 1, 2, 3]
Keep in mind that a string is an iterable, so if you extend a list with a string, you'll append each character as you iterate over the string (which may not be what you want):
>>> my_list.extend('baz')
>>> my_list
['foo', 'bar', 1, 2, 3, 'b', 'a', 'z']
Operator Overload, __add__ (+) and __iadd__ (+=)
Both + and += operators are defined for list. They are semantically similar to extend.
my_list + another_list creates a third list in memory, so you can return the result of it, but it requires that the second iterable be a list.
my_list += another_list modifies the list in-place (it is the in-place operator, and lists are mutable objects, as we've seen) so it does not create a new list. It also works like extend, in that the second iterable can be any kind of iterable.
Don't get confused - my_list = my_list + another_list is not equivalent to += - it gives you a brand new list assigned to my_list.
Time Complexity
Append has (amortized) constant time complexity, O(1).
Extend has time complexity, O(k).
Iterating through the multiple calls to append adds to the complexity, making it equivalent to that of extend, and since extend's iteration is implemented in C, it will always be faster if you intend to append successive items from an iterable onto a list.
Regarding "amortized" - from the list object implementation source:
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
This means that we get the benefits of a larger than needed memory reallocation up front, but we may pay for it on the next marginal reallocation with an even larger one. Total time for all appends is linear at O(n), and that time allocated per append, becomes O(1).
Performance
You may wonder what is more performant, since append can be used to achieve the same outcome as extend. The following functions do the same thing:
def append(alist, iterable):
for item in iterable:
alist.append(item)
def extend(alist, iterable):
alist.extend(iterable)
So let's time them:
import timeit
>>> min(timeit.repeat(lambda: append([], "abcdefghijklmnopqrstuvwxyz")))
2.867846965789795
>>> min(timeit.repeat(lambda: extend([], "abcdefghijklmnopqrstuvwxyz")))
0.8060121536254883
Addressing a comment on timings
A commenter said:
Perfect answer, I just miss the timing of comparing adding only one element
Do the semantically correct thing. If you want to append all elements in an iterable, use extend. If you're just adding one element, use append.
Ok, so let's create an experiment to see how this works out in time:
def append_one(a_list, element):
a_list.append(element)
def extend_one(a_list, element):
"""creating a new list is semantically the most direct
way to create an iterable to give to extend"""
a_list.extend([element])
import timeit
And we see that going out of our way to create an iterable just to use extend is a (minor) waste of time:
>>> min(timeit.repeat(lambda: append_one([], 0)))
0.2082819009956438
>>> min(timeit.repeat(lambda: extend_one([], 0)))
0.2397019260097295
We learn from this that there's nothing gained from using extend when we have only one element to append.
Also, these timings are not that important. I am just showing them to make the point that, in Python, doing the semantically correct thing is doing things the Right Way™.
It's conceivable that you might test timings on two comparable operations and get an ambiguous or inverse result. Just focus on doing the semantically correct thing.
Conclusion
We see that extend is semantically clearer, and that it can run much faster than append, when you intend to append each element in an iterable to a list.
If you only have a single element (not in an iterable) to add to the list, use append.
append appends a single element. extend appends a list of elements.
Note that if you pass a list to append, it still adds one element:
>>> a = [1, 2, 3]
>>> a.append([4, 5, 6])
>>> a
[1, 2, 3, [4, 5, 6]]
Append vs Extend
With append you can append a single element that will extend the list:
>>> a = [1,2]
>>> a.append(3)
>>> a
[1,2,3]
If you want to extend more than one element you should use extend, because you can only append one elment or one list of element:
>>> a.append([4,5])
>>> a
>>> [1,2,3,[4,5]]
So that you get a nested list
Instead with extend, you can extend a single element like this
>>> a = [1,2]
>>> a.extend([3])
>>> a
[1,2,3]
Or, differently, from append, extend more elements in one time without nesting the list into the original one (that's the reason of the name extend)
>>> a.extend([4,5,6])
>>> a
[1,2,3,4,5,6]
Adding one element with both methods
Both append and extend can add one element to the end of the list, though append is simpler.
append 1 element
>>> x = [1,2]
>>> x.append(3)
>>> x
[1,2,3]
extend one element
>>> x = [1,2]
>>> x.extend([3])
>>> x
[1,2,3]
Adding more elements... with different results
If you use append for more than one element, you have to pass a list of elements as arguments and you will obtain a NESTED list!
>>> x = [1,2]
>>> x.append([3,4])
>>> x
[1,2,[3,4]]
With extend, instead, you pass a list as an argument, but you will obtain a list with the new element that is not nested in the old one.
>>> z = [1,2]
>>> z.extend([3,4])
>>> z
[1,2,3,4]
So, with more elements, you will use extend to get a list with more items.
However, appending a list will not add more elements to the list, but one element that is a nested list as you can clearly see in the output of the code.
The following two snippets are semantically equivalent:
for item in iterator:
a_list.append(item)
and
a_list.extend(iterator)
The latter may be faster as the loop is implemented in C.
The append() method adds a single item to the end of the list.
x = [1, 2, 3]
x.append([4, 5])
x.append('abc')
print(x)
# gives you
[1, 2, 3, [4, 5], 'abc']
The extend() method takes one argument, a list, and appends each of the items of the argument to the original list. (Lists are implemented as classes. “Creating” a list is really instantiating a class. As such, a list has methods that operate on it.)
x = [1, 2, 3]
x.extend([4, 5])
x.extend('abc')
print(x)
# gives you
[1, 2, 3, 4, 5, 'a', 'b', 'c']
From Dive Into Python.
You can use "+" for returning extend, instead of extending in place.
l1=range(10)
l1+[11]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]
l2=range(10,1,-1)
l1+l2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2]
Similarly += for in place behavior, but with slight differences from append & extend. One of the biggest differences of += from append and extend is when it is used in function scopes, see this blog post.
append(object) updates the list by adding the object to the list.
x = [20]
# List passed to the append(object) method is treated as a single object.
x.append([21, 22, 23])
# Hence the resultant list length will be 2
print(x)
--> [20, [21, 22, 23]]
extend(list) concatenates the two lists essentially.
x = [20]
# The parameter passed to extend(list) method is treated as a list.
# Eventually it is two lists being concatenated.
x.extend([21, 22, 23])
# Here the resultant list's length is 4
print(x)
--> [20, 21, 22, 23]
This is the equivalent of append and extend using the + operator:
>>> x = [1,2,3]
>>> x
[1, 2, 3]
>>> x = x + [4,5,6] # Extend
>>> x
[1, 2, 3, 4, 5, 6]
>>> x = x + [[7,8]] # Append
>>> x
[1, 2, 3, 4, 5, 6, [7, 8]]
extend() can be used with an iterator argument. Here is an example. You wish to make a list out of a list of lists this way:
From
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
you want
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
You may use itertools.chain.from_iterable() to do so. This method's output is an iterator. Its implementation is equivalent to
def from_iterable(iterables):
# chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
for it in iterables:
for element in it:
yield element
Back to our example, we can do
import itertools
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))
and get the wanted list.
Here is how equivalently extend() can be used with an iterator argument:
merged = []
merged.extend(itertools.chain.from_iterable(list2d))
print(merged)
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
append(): It is basically used in Python to add one element.
Example 1:
>> a = [1, 2, 3, 4]
>> a.append(5)
>> print(a)
>> a = [1, 2, 3, 4, 5]
Example 2:
>> a = [1, 2, 3, 4]
>> a.append([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, [5, 6]]
extend(): Where extend(), is used to merge two lists or insert multiple elements in one list.
Example 1:
>> a = [1, 2, 3, 4]
>> b = [5, 6, 7, 8]
>> a.extend(b)
>> print(a)
>> a = [1, 2, 3, 4, 5, 6, 7, 8]
Example 2:
>> a = [1, 2, 3, 4]
>> a.extend([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, 5, 6]
An interesting point that has been hinted, but not explained, is that extend is faster than append. For any loop that has append inside should be considered to be replaced by list.extend(processed_elements).
Bear in mind that apprending new elements might result in the realloaction of the whole list to a better location in memory. If this is done several times because we are appending 1 element at a time, overall performance suffers. In this sense, list.extend is analogous to "".join(stringlist).
Append adds the entire data at once. The whole data will be added to the newly created index. On the other hand, extend, as it name suggests, extends the current array.
For example
list1 = [123, 456, 678]
list2 = [111, 222]
With append we get:
result = [123, 456, 678, [111, 222]]
While on extend we get:
result = [123, 456, 678, 111, 222]
An English dictionary defines the words append and extend as:
append: add (something) to the end of a written document.
extend: make larger. Enlarge or expand
With that knowledge, now let's understand
1) The difference between append and extend
append:
Appends any Python object as-is to the end of the list (i.e. as a
the last element in the list).
The resulting list may be nested and contain heterogeneous elements (i.e. list, string, tuple, dictionary, set, etc.)
extend:
Accepts any iterable as its argument and makes the list larger.
The resulting list is always one-dimensional list (i.e. no nesting) and it may contain heterogeneous elements in it (e.g. characters, integers, float) as a result of applying list(iterable).
2) Similarity between append and extend
Both take exactly one argument.
Both modify the list in-place.
As a result, both returns None.
Example
lis = [1, 2, 3]
# 'extend' is equivalent to this
lis = lis + list(iterable)
# 'append' simply appends its argument as the last element to the list
# as long as the argument is a valid Python object
list.append(object)
I hope I can make a useful supplement to this question. If your list stores a specific type object, for example Info, here is a situation that extend method is not suitable: In a for loop and and generating an Info object every time and using extend to store it into your list, it will fail. The exception is like below:
TypeError: 'Info' object is not iterable
But if you use the append method, the result is OK. Because every time using the extend method, it will always treat it as a list or any other collection type, iterate it, and place it after the previous list. A specific object can not be iterated, obviously.
To distinguish them intuitively
l1 = ['a', 'b', 'c']
l2 = ['d', 'e', 'f']
l1.append(l2)
l1
['a', 'b', 'c', ['d', 'e', 'f']]
It's like l1 reproduce a body inside her body(nested).
# Reset l1 = ['a', 'b', 'c']
l1.extend(l2)
l1
['a', 'b', 'c', 'd', 'e', 'f']
It's like that two separated individuals get married and construct an united family.
Besides I make an exhaustive cheatsheet of all list's methods for your reference.
list_methods = {'Add': {'extend', 'append', 'insert'},
'Remove': {'pop', 'remove', 'clear'}
'Sort': {'reverse', 'sort'},
'Search': {'count', 'index'},
'Copy': {'copy'},
}
extend(L) extends the list by appending all the items in the given list L.
>>> a
[1, 2, 3]
a.extend([4]) #is eqivalent of a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
a = [1, 2, 3]
>>> a
[1, 2, 3]
>>> a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
append "extends" the list (in place) by only one item, the single object passed (as argument).
extend "extends" the list (in place) by as many items as the object passed (as argument) contains.
This may be slightly confusing for str objects.
If you pass a string as argument:
append will add a single string item at the end but
extend will add as many "single" 'str' items as the length of that string.
If you pass a list of strings as argument:
append will still add a single 'list' item at the end and
extend will add as many 'list' items as the length of the passed list.
def append_o(a_list, element):
a_list.append(element)
print('append:', end = ' ')
for item in a_list:
print(item, end = ',')
print()
def extend_o(a_list, element):
a_list.extend(element)
print('extend:', end = ' ')
for item in a_list:
print(item, end = ',')
print()
append_o(['ab'],'cd')
extend_o(['ab'],'cd')
append_o(['ab'],['cd', 'ef'])
extend_o(['ab'],['cd', 'ef'])
append_o(['ab'],['cd'])
extend_o(['ab'],['cd'])
produces:
append: ab,cd,
extend: ab,c,d,
append: ab,['cd', 'ef'],
extend: ab,cd,ef,
append: ab,['cd'],
extend: ab,cd,
Append and extend are one of the extensibility mechanisms in python.
Append: Adds an element to the end of the list.
my_list = [1,2,3,4]
To add a new element to the list, we can use append method in the following way.
my_list.append(5)
The default location that the new element will be added is always in the (length+1) position.
Insert: The insert method was used to overcome the limitations of append. With insert, we can explicitly define the exact position we want our new element to be inserted at.
Method descriptor of insert(index, object). It takes two arguments, first being the index we want to insert our element and second the element itself.
Example: my_list = [1,2,3,4]
my_list[4, 'a']
my_list
[1,2,3,4,'a']
Extend: This is very useful when we want to join two or more lists into a single list. Without extend, if we want to join two lists, the resulting object will contain a list of lists.
a = [1,2]
b = [3]
a.append(b)
print (a)
[1,2,[3]]
If we try to access the element at pos 2, we get a list ([3]), instead of the element. To join two lists, we'll have to use append.
a = [1,2]
b = [3]
a.extend(b)
print (a)
[1,2,3]
To join multiple lists
a = [1]
b = [2]
c = [3]
a.extend(b+c)
print (a)
[1,2,3]

How to append two argument items into a stack (Python3) [duplicate]

This question's answers are a community effort. Edit existing answers to improve this post. It is not currently accepting new answers or interactions.
What's the difference between the list methods append() and extend()?
append appends a specified object at the end of the list:
>>> x = [1, 2, 3]
>>> x.append([4, 5])
>>> print(x)
[1, 2, 3, [4, 5]]
extend extends the list by appending elements from the specified iterable:
>>> x = [1, 2, 3]
>>> x.extend([4, 5])
>>> print(x)
[1, 2, 3, 4, 5]
append adds an element to a list. extend concatenates the first list with another list/iterable.
>>> xs = ['A', 'B']
>>> xs
['A', 'B']
>>> xs.append("D")
>>> xs
['A', 'B', 'D']
>>> xs.append(["E", "F"])
>>> xs
['A', 'B', 'D', ['E', 'F']]
>>> xs.insert(2, "C")
>>> xs
['A', 'B', 'C', 'D', ['E', 'F']]
>>> xs.extend(["G", "H"])
>>> xs
['A', 'B', 'C', 'D', ['E', 'F'], 'G', 'H']
What is the difference between the list methods append and extend?
append adds its argument as a single element to the end of a list. The length of the list itself will increase by one.
extend iterates over its argument adding each element to the list, extending the list. The length of the list will increase by however many elements were in the iterable argument.
append
The list.append method appends an object to the end of the list.
my_list.append(object)
Whatever the object is, whether a number, a string, another list, or something else, it gets added onto the end of my_list as a single entry on the list.
>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
So keep in mind that a list is an object. If you append another list onto a list, the first list will be a single object at the end of the list (which may not be what you want):
>>> another_list = [1, 2, 3]
>>> my_list.append(another_list)
>>> my_list
['foo', 'bar', 'baz', [1, 2, 3]]
#^^^^^^^^^--- single item at the end of the list.
extend
The list.extend method extends a list by appending elements from an iterable:
my_list.extend(iterable)
So with extend, each element of the iterable gets appended onto the list. For example:
>>> my_list
['foo', 'bar']
>>> another_list = [1, 2, 3]
>>> my_list.extend(another_list)
>>> my_list
['foo', 'bar', 1, 2, 3]
Keep in mind that a string is an iterable, so if you extend a list with a string, you'll append each character as you iterate over the string (which may not be what you want):
>>> my_list.extend('baz')
>>> my_list
['foo', 'bar', 1, 2, 3, 'b', 'a', 'z']
Operator Overload, __add__ (+) and __iadd__ (+=)
Both + and += operators are defined for list. They are semantically similar to extend.
my_list + another_list creates a third list in memory, so you can return the result of it, but it requires that the second iterable be a list.
my_list += another_list modifies the list in-place (it is the in-place operator, and lists are mutable objects, as we've seen) so it does not create a new list. It also works like extend, in that the second iterable can be any kind of iterable.
Don't get confused - my_list = my_list + another_list is not equivalent to += - it gives you a brand new list assigned to my_list.
Time Complexity
Append has (amortized) constant time complexity, O(1).
Extend has time complexity, O(k).
Iterating through the multiple calls to append adds to the complexity, making it equivalent to that of extend, and since extend's iteration is implemented in C, it will always be faster if you intend to append successive items from an iterable onto a list.
Regarding "amortized" - from the list object implementation source:
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
This means that we get the benefits of a larger than needed memory reallocation up front, but we may pay for it on the next marginal reallocation with an even larger one. Total time for all appends is linear at O(n), and that time allocated per append, becomes O(1).
Performance
You may wonder what is more performant, since append can be used to achieve the same outcome as extend. The following functions do the same thing:
def append(alist, iterable):
for item in iterable:
alist.append(item)
def extend(alist, iterable):
alist.extend(iterable)
So let's time them:
import timeit
>>> min(timeit.repeat(lambda: append([], "abcdefghijklmnopqrstuvwxyz")))
2.867846965789795
>>> min(timeit.repeat(lambda: extend([], "abcdefghijklmnopqrstuvwxyz")))
0.8060121536254883
Addressing a comment on timings
A commenter said:
Perfect answer, I just miss the timing of comparing adding only one element
Do the semantically correct thing. If you want to append all elements in an iterable, use extend. If you're just adding one element, use append.
Ok, so let's create an experiment to see how this works out in time:
def append_one(a_list, element):
a_list.append(element)
def extend_one(a_list, element):
"""creating a new list is semantically the most direct
way to create an iterable to give to extend"""
a_list.extend([element])
import timeit
And we see that going out of our way to create an iterable just to use extend is a (minor) waste of time:
>>> min(timeit.repeat(lambda: append_one([], 0)))
0.2082819009956438
>>> min(timeit.repeat(lambda: extend_one([], 0)))
0.2397019260097295
We learn from this that there's nothing gained from using extend when we have only one element to append.
Also, these timings are not that important. I am just showing them to make the point that, in Python, doing the semantically correct thing is doing things the Right Way™.
It's conceivable that you might test timings on two comparable operations and get an ambiguous or inverse result. Just focus on doing the semantically correct thing.
Conclusion
We see that extend is semantically clearer, and that it can run much faster than append, when you intend to append each element in an iterable to a list.
If you only have a single element (not in an iterable) to add to the list, use append.
append appends a single element. extend appends a list of elements.
Note that if you pass a list to append, it still adds one element:
>>> a = [1, 2, 3]
>>> a.append([4, 5, 6])
>>> a
[1, 2, 3, [4, 5, 6]]
Append vs Extend
With append you can append a single element that will extend the list:
>>> a = [1,2]
>>> a.append(3)
>>> a
[1,2,3]
If you want to extend more than one element you should use extend, because you can only append one elment or one list of element:
>>> a.append([4,5])
>>> a
>>> [1,2,3,[4,5]]
So that you get a nested list
Instead with extend, you can extend a single element like this
>>> a = [1,2]
>>> a.extend([3])
>>> a
[1,2,3]
Or, differently, from append, extend more elements in one time without nesting the list into the original one (that's the reason of the name extend)
>>> a.extend([4,5,6])
>>> a
[1,2,3,4,5,6]
Adding one element with both methods
Both append and extend can add one element to the end of the list, though append is simpler.
append 1 element
>>> x = [1,2]
>>> x.append(3)
>>> x
[1,2,3]
extend one element
>>> x = [1,2]
>>> x.extend([3])
>>> x
[1,2,3]
Adding more elements... with different results
If you use append for more than one element, you have to pass a list of elements as arguments and you will obtain a NESTED list!
>>> x = [1,2]
>>> x.append([3,4])
>>> x
[1,2,[3,4]]
With extend, instead, you pass a list as an argument, but you will obtain a list with the new element that is not nested in the old one.
>>> z = [1,2]
>>> z.extend([3,4])
>>> z
[1,2,3,4]
So, with more elements, you will use extend to get a list with more items.
However, appending a list will not add more elements to the list, but one element that is a nested list as you can clearly see in the output of the code.
The following two snippets are semantically equivalent:
for item in iterator:
a_list.append(item)
and
a_list.extend(iterator)
The latter may be faster as the loop is implemented in C.
The append() method adds a single item to the end of the list.
x = [1, 2, 3]
x.append([4, 5])
x.append('abc')
print(x)
# gives you
[1, 2, 3, [4, 5], 'abc']
The extend() method takes one argument, a list, and appends each of the items of the argument to the original list. (Lists are implemented as classes. “Creating” a list is really instantiating a class. As such, a list has methods that operate on it.)
x = [1, 2, 3]
x.extend([4, 5])
x.extend('abc')
print(x)
# gives you
[1, 2, 3, 4, 5, 'a', 'b', 'c']
From Dive Into Python.
You can use "+" for returning extend, instead of extending in place.
l1=range(10)
l1+[11]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]
l2=range(10,1,-1)
l1+l2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2]
Similarly += for in place behavior, but with slight differences from append & extend. One of the biggest differences of += from append and extend is when it is used in function scopes, see this blog post.
append(object) updates the list by adding the object to the list.
x = [20]
# List passed to the append(object) method is treated as a single object.
x.append([21, 22, 23])
# Hence the resultant list length will be 2
print(x)
--> [20, [21, 22, 23]]
extend(list) concatenates the two lists essentially.
x = [20]
# The parameter passed to extend(list) method is treated as a list.
# Eventually it is two lists being concatenated.
x.extend([21, 22, 23])
# Here the resultant list's length is 4
print(x)
--> [20, 21, 22, 23]
This is the equivalent of append and extend using the + operator:
>>> x = [1,2,3]
>>> x
[1, 2, 3]
>>> x = x + [4,5,6] # Extend
>>> x
[1, 2, 3, 4, 5, 6]
>>> x = x + [[7,8]] # Append
>>> x
[1, 2, 3, 4, 5, 6, [7, 8]]
extend() can be used with an iterator argument. Here is an example. You wish to make a list out of a list of lists this way:
From
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
you want
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
You may use itertools.chain.from_iterable() to do so. This method's output is an iterator. Its implementation is equivalent to
def from_iterable(iterables):
# chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
for it in iterables:
for element in it:
yield element
Back to our example, we can do
import itertools
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))
and get the wanted list.
Here is how equivalently extend() can be used with an iterator argument:
merged = []
merged.extend(itertools.chain.from_iterable(list2d))
print(merged)
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
append(): It is basically used in Python to add one element.
Example 1:
>> a = [1, 2, 3, 4]
>> a.append(5)
>> print(a)
>> a = [1, 2, 3, 4, 5]
Example 2:
>> a = [1, 2, 3, 4]
>> a.append([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, [5, 6]]
extend(): Where extend(), is used to merge two lists or insert multiple elements in one list.
Example 1:
>> a = [1, 2, 3, 4]
>> b = [5, 6, 7, 8]
>> a.extend(b)
>> print(a)
>> a = [1, 2, 3, 4, 5, 6, 7, 8]
Example 2:
>> a = [1, 2, 3, 4]
>> a.extend([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, 5, 6]
An interesting point that has been hinted, but not explained, is that extend is faster than append. For any loop that has append inside should be considered to be replaced by list.extend(processed_elements).
Bear in mind that apprending new elements might result in the realloaction of the whole list to a better location in memory. If this is done several times because we are appending 1 element at a time, overall performance suffers. In this sense, list.extend is analogous to "".join(stringlist).
Append adds the entire data at once. The whole data will be added to the newly created index. On the other hand, extend, as it name suggests, extends the current array.
For example
list1 = [123, 456, 678]
list2 = [111, 222]
With append we get:
result = [123, 456, 678, [111, 222]]
While on extend we get:
result = [123, 456, 678, 111, 222]
An English dictionary defines the words append and extend as:
append: add (something) to the end of a written document.
extend: make larger. Enlarge or expand
With that knowledge, now let's understand
1) The difference between append and extend
append:
Appends any Python object as-is to the end of the list (i.e. as a
the last element in the list).
The resulting list may be nested and contain heterogeneous elements (i.e. list, string, tuple, dictionary, set, etc.)
extend:
Accepts any iterable as its argument and makes the list larger.
The resulting list is always one-dimensional list (i.e. no nesting) and it may contain heterogeneous elements in it (e.g. characters, integers, float) as a result of applying list(iterable).
2) Similarity between append and extend
Both take exactly one argument.
Both modify the list in-place.
As a result, both returns None.
Example
lis = [1, 2, 3]
# 'extend' is equivalent to this
lis = lis + list(iterable)
# 'append' simply appends its argument as the last element to the list
# as long as the argument is a valid Python object
list.append(object)
I hope I can make a useful supplement to this question. If your list stores a specific type object, for example Info, here is a situation that extend method is not suitable: In a for loop and and generating an Info object every time and using extend to store it into your list, it will fail. The exception is like below:
TypeError: 'Info' object is not iterable
But if you use the append method, the result is OK. Because every time using the extend method, it will always treat it as a list or any other collection type, iterate it, and place it after the previous list. A specific object can not be iterated, obviously.
To distinguish them intuitively
l1 = ['a', 'b', 'c']
l2 = ['d', 'e', 'f']
l1.append(l2)
l1
['a', 'b', 'c', ['d', 'e', 'f']]
It's like l1 reproduce a body inside her body(nested).
# Reset l1 = ['a', 'b', 'c']
l1.extend(l2)
l1
['a', 'b', 'c', 'd', 'e', 'f']
It's like that two separated individuals get married and construct an united family.
Besides I make an exhaustive cheatsheet of all list's methods for your reference.
list_methods = {'Add': {'extend', 'append', 'insert'},
'Remove': {'pop', 'remove', 'clear'}
'Sort': {'reverse', 'sort'},
'Search': {'count', 'index'},
'Copy': {'copy'},
}
extend(L) extends the list by appending all the items in the given list L.
>>> a
[1, 2, 3]
a.extend([4]) #is eqivalent of a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
a = [1, 2, 3]
>>> a
[1, 2, 3]
>>> a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
append "extends" the list (in place) by only one item, the single object passed (as argument).
extend "extends" the list (in place) by as many items as the object passed (as argument) contains.
This may be slightly confusing for str objects.
If you pass a string as argument:
append will add a single string item at the end but
extend will add as many "single" 'str' items as the length of that string.
If you pass a list of strings as argument:
append will still add a single 'list' item at the end and
extend will add as many 'list' items as the length of the passed list.
def append_o(a_list, element):
a_list.append(element)
print('append:', end = ' ')
for item in a_list:
print(item, end = ',')
print()
def extend_o(a_list, element):
a_list.extend(element)
print('extend:', end = ' ')
for item in a_list:
print(item, end = ',')
print()
append_o(['ab'],'cd')
extend_o(['ab'],'cd')
append_o(['ab'],['cd', 'ef'])
extend_o(['ab'],['cd', 'ef'])
append_o(['ab'],['cd'])
extend_o(['ab'],['cd'])
produces:
append: ab,cd,
extend: ab,c,d,
append: ab,['cd', 'ef'],
extend: ab,cd,ef,
append: ab,['cd'],
extend: ab,cd,
Append and extend are one of the extensibility mechanisms in python.
Append: Adds an element to the end of the list.
my_list = [1,2,3,4]
To add a new element to the list, we can use append method in the following way.
my_list.append(5)
The default location that the new element will be added is always in the (length+1) position.
Insert: The insert method was used to overcome the limitations of append. With insert, we can explicitly define the exact position we want our new element to be inserted at.
Method descriptor of insert(index, object). It takes two arguments, first being the index we want to insert our element and second the element itself.
Example: my_list = [1,2,3,4]
my_list[4, 'a']
my_list
[1,2,3,4,'a']
Extend: This is very useful when we want to join two or more lists into a single list. Without extend, if we want to join two lists, the resulting object will contain a list of lists.
a = [1,2]
b = [3]
a.append(b)
print (a)
[1,2,[3]]
If we try to access the element at pos 2, we get a list ([3]), instead of the element. To join two lists, we'll have to use append.
a = [1,2]
b = [3]
a.extend(b)
print (a)
[1,2,3]
To join multiple lists
a = [1]
b = [2]
c = [3]
a.extend(b+c)
print (a)
[1,2,3]

python list comprehension and extend() [duplicate]

This question already has answers here:
Why do these list operations (methods: clear / extend / reverse / append / sort / remove) return None, rather than the resulting list?
(6 answers)
Closed 5 months ago.
Working my way into Python (2.7.1)
But failing to make sense (for hours) of this:
>>> a = [1, 2]
>>> b = [3, 4]
>>>
>>> a.extend([b[0]])
>>> a
[1, 2, 3]
>>>
>>> a.extend([b[1]])
>>> a
[1, 2, 3, 4]
>>>
>>> m = [a.extend([b[i]]) for i in range(len(b))] # list of lists
>>> m
[None, None]
The first two extends work as expected, but when compacting the same in a list comprehension it fails.
What am i doing wrong?
extend modifies the list in-place.
>>> [a + b[0:i] for i in range(len(b)+1)]
[[1, 2], [1, 2, 3], [1, 2, 3, 4]]
list.extend() extends a list in place. Python standard library methods that alter objects in-place always return None (the default); your list comprehension executed a.extend() twice and thus the resulting list consists of two None return values.
Your a.extend() calls otherwise worked just fine; if you were to print a it would show:
[1, 2, 3, 4, 3, 4]
You don't see the None return value in the Python interpreter, because the interpreter never echoes None results. You could test for that explicitly:
>>> a = []
>>> a.extend(['foo', 'bar']) is None
True
>>> a
['foo', 'bar']
the return value of extend is None.
extend function extends the list with the value you've provided in-place and returns None. That's why you have two None values in your list. I propose you rewrite your comprehension like so:
a = [1, 2]
b = [3, 4]
m = [a + [v] for v in b] # m is [[1,2,3],[1,2,4]]
For python lists, methods that change the list work in place and return None. This applies to extendas well as to append, remove, insert, ...
In reply to an older question, I sketched an subclass of list that would behave as you expected list to work.
Why does [].append() not work in python?
This is intended as educational. For pros and cons.. look at the comments to my answer.
I like this for the ability of chaining methods and working in a fluent style, e.g. then something like
li = FluentList()
li.extend([1,4,6]).remove(4).append(7).insert(1,10).reverse().sort(key=lambda x:x%2)
would be possible.
a.extend() returns None.
You probably want one of these:
>>> m = a + b
>>> m
[1, 2, 3, 4]
>>> a.extend(b)
>>> a
[1, 2, 3, 4]
Aside from that, if you want to iterate over all elements of a list, you just can do it like that:
m = [somefunction(element) for element in somelist]
or
for element in somelist:
do_some_thing(element)
In most cases there is no need to go over the indices.
And if you want to add just one element to a list, you should use somelist.append(element) instead of `somelist.extend([element])

Python a = a.reverse makes the list empty?

At the interpreter,
a = [1,2,3,4]
a = a.reverse()
Next when I type a at the interpreter, I get nothing. So it seems a = a.reverse() generates an empty list. Is this by design?
I am using python 2.5 on windows xp.
list.reverse() modifies the list in-place, returns None. But if you want to protect old list, you can use reversed() function for that, it returns an iterator.
In [1]: a=[1,2,3,4]
In [2]: print(a.reverse())
None
In [3]: a
Out[3]: [4, 3, 2, 1]
In [4]: a=[1,2,3,4]
In [5]: print(reversed(a))
<listreverseiterator object at 0x24e7e50>
In [6]: list(reversed(a))
Out[6]: [4, 3, 2, 1]
In [7]: a
Out[7]: [1, 2, 3, 4]
reverse changes list in-place, and doesn't return anything. Thus, this is the expected usage:
a = [1, 2, 3, 4]
a.reverse()
a # => [4, 3, 2, 1]
If you assign the result of reverse back to a, you will overwrite all its hard work with the nonsensical return value (None), which is where your bug comes from.
list is a mutable type, so list operations are in-place, and return None.
The built-in method reverse of a list on python doesn't return the reversed list.
It reverses the list in place.
So, if you want to reverse your list, like in your code, just do:
a = [1,2,3,4]
a.reverse()
list.reverse() just doesn't return anything, because it changes the list in-place. See this example:
>>> a = [1,2,3,4]
>>> a.reverse()
>>> a
[4, 3, 2, 1]
There also is the reversed function (actually a type, but doesn't matter here), which does not change the list in-place, but instead returns an iterator with the list items in the reverse order. Try:
>>> a = [1,2,3,4]
>>> a = list(reversed(a))
>>> a
[4, 3, 2, 1]
I think what you want to do is:
a = [1,2,3,4]
a.reverse()
a is an object and the operations work on it's data, so you don't need to assign again it.
The reverse method does the reverse 'in place' (like sort) and returns None, so after calling a.reverse() a already contains the result.

What is the difference between Python's list methods append and extend?

This question's answers are a community effort. Edit existing answers to improve this post. It is not currently accepting new answers or interactions.
What's the difference between the list methods append() and extend()?
append appends a specified object at the end of the list:
>>> x = [1, 2, 3]
>>> x.append([4, 5])
>>> print(x)
[1, 2, 3, [4, 5]]
extend extends the list by appending elements from the specified iterable:
>>> x = [1, 2, 3]
>>> x.extend([4, 5])
>>> print(x)
[1, 2, 3, 4, 5]
append adds an element to a list. extend concatenates the first list with another list/iterable.
>>> xs = ['A', 'B']
>>> xs
['A', 'B']
>>> xs.append("D")
>>> xs
['A', 'B', 'D']
>>> xs.append(["E", "F"])
>>> xs
['A', 'B', 'D', ['E', 'F']]
>>> xs.insert(2, "C")
>>> xs
['A', 'B', 'C', 'D', ['E', 'F']]
>>> xs.extend(["G", "H"])
>>> xs
['A', 'B', 'C', 'D', ['E', 'F'], 'G', 'H']
What is the difference between the list methods append and extend?
append adds its argument as a single element to the end of a list. The length of the list itself will increase by one.
extend iterates over its argument adding each element to the list, extending the list. The length of the list will increase by however many elements were in the iterable argument.
append
The list.append method appends an object to the end of the list.
my_list.append(object)
Whatever the object is, whether a number, a string, another list, or something else, it gets added onto the end of my_list as a single entry on the list.
>>> my_list
['foo', 'bar']
>>> my_list.append('baz')
>>> my_list
['foo', 'bar', 'baz']
So keep in mind that a list is an object. If you append another list onto a list, the first list will be a single object at the end of the list (which may not be what you want):
>>> another_list = [1, 2, 3]
>>> my_list.append(another_list)
>>> my_list
['foo', 'bar', 'baz', [1, 2, 3]]
#^^^^^^^^^--- single item at the end of the list.
extend
The list.extend method extends a list by appending elements from an iterable:
my_list.extend(iterable)
So with extend, each element of the iterable gets appended onto the list. For example:
>>> my_list
['foo', 'bar']
>>> another_list = [1, 2, 3]
>>> my_list.extend(another_list)
>>> my_list
['foo', 'bar', 1, 2, 3]
Keep in mind that a string is an iterable, so if you extend a list with a string, you'll append each character as you iterate over the string (which may not be what you want):
>>> my_list.extend('baz')
>>> my_list
['foo', 'bar', 1, 2, 3, 'b', 'a', 'z']
Operator Overload, __add__ (+) and __iadd__ (+=)
Both + and += operators are defined for list. They are semantically similar to extend.
my_list + another_list creates a third list in memory, so you can return the result of it, but it requires that the second iterable be a list.
my_list += another_list modifies the list in-place (it is the in-place operator, and lists are mutable objects, as we've seen) so it does not create a new list. It also works like extend, in that the second iterable can be any kind of iterable.
Don't get confused - my_list = my_list + another_list is not equivalent to += - it gives you a brand new list assigned to my_list.
Time Complexity
Append has (amortized) constant time complexity, O(1).
Extend has time complexity, O(k).
Iterating through the multiple calls to append adds to the complexity, making it equivalent to that of extend, and since extend's iteration is implemented in C, it will always be faster if you intend to append successive items from an iterable onto a list.
Regarding "amortized" - from the list object implementation source:
/* This over-allocates proportional to the list size, making room
* for additional growth. The over-allocation is mild, but is
* enough to give linear-time amortized behavior over a long
* sequence of appends() in the presence of a poorly-performing
* system realloc().
This means that we get the benefits of a larger than needed memory reallocation up front, but we may pay for it on the next marginal reallocation with an even larger one. Total time for all appends is linear at O(n), and that time allocated per append, becomes O(1).
Performance
You may wonder what is more performant, since append can be used to achieve the same outcome as extend. The following functions do the same thing:
def append(alist, iterable):
for item in iterable:
alist.append(item)
def extend(alist, iterable):
alist.extend(iterable)
So let's time them:
import timeit
>>> min(timeit.repeat(lambda: append([], "abcdefghijklmnopqrstuvwxyz")))
2.867846965789795
>>> min(timeit.repeat(lambda: extend([], "abcdefghijklmnopqrstuvwxyz")))
0.8060121536254883
Addressing a comment on timings
A commenter said:
Perfect answer, I just miss the timing of comparing adding only one element
Do the semantically correct thing. If you want to append all elements in an iterable, use extend. If you're just adding one element, use append.
Ok, so let's create an experiment to see how this works out in time:
def append_one(a_list, element):
a_list.append(element)
def extend_one(a_list, element):
"""creating a new list is semantically the most direct
way to create an iterable to give to extend"""
a_list.extend([element])
import timeit
And we see that going out of our way to create an iterable just to use extend is a (minor) waste of time:
>>> min(timeit.repeat(lambda: append_one([], 0)))
0.2082819009956438
>>> min(timeit.repeat(lambda: extend_one([], 0)))
0.2397019260097295
We learn from this that there's nothing gained from using extend when we have only one element to append.
Also, these timings are not that important. I am just showing them to make the point that, in Python, doing the semantically correct thing is doing things the Right Way™.
It's conceivable that you might test timings on two comparable operations and get an ambiguous or inverse result. Just focus on doing the semantically correct thing.
Conclusion
We see that extend is semantically clearer, and that it can run much faster than append, when you intend to append each element in an iterable to a list.
If you only have a single element (not in an iterable) to add to the list, use append.
append appends a single element. extend appends a list of elements.
Note that if you pass a list to append, it still adds one element:
>>> a = [1, 2, 3]
>>> a.append([4, 5, 6])
>>> a
[1, 2, 3, [4, 5, 6]]
Append vs Extend
With append you can append a single element that will extend the list:
>>> a = [1,2]
>>> a.append(3)
>>> a
[1,2,3]
If you want to extend more than one element you should use extend, because you can only append one elment or one list of element:
>>> a.append([4,5])
>>> a
>>> [1,2,3,[4,5]]
So that you get a nested list
Instead with extend, you can extend a single element like this
>>> a = [1,2]
>>> a.extend([3])
>>> a
[1,2,3]
Or, differently, from append, extend more elements in one time without nesting the list into the original one (that's the reason of the name extend)
>>> a.extend([4,5,6])
>>> a
[1,2,3,4,5,6]
Adding one element with both methods
Both append and extend can add one element to the end of the list, though append is simpler.
append 1 element
>>> x = [1,2]
>>> x.append(3)
>>> x
[1,2,3]
extend one element
>>> x = [1,2]
>>> x.extend([3])
>>> x
[1,2,3]
Adding more elements... with different results
If you use append for more than one element, you have to pass a list of elements as arguments and you will obtain a NESTED list!
>>> x = [1,2]
>>> x.append([3,4])
>>> x
[1,2,[3,4]]
With extend, instead, you pass a list as an argument, but you will obtain a list with the new element that is not nested in the old one.
>>> z = [1,2]
>>> z.extend([3,4])
>>> z
[1,2,3,4]
So, with more elements, you will use extend to get a list with more items.
However, appending a list will not add more elements to the list, but one element that is a nested list as you can clearly see in the output of the code.
The following two snippets are semantically equivalent:
for item in iterator:
a_list.append(item)
and
a_list.extend(iterator)
The latter may be faster as the loop is implemented in C.
The append() method adds a single item to the end of the list.
x = [1, 2, 3]
x.append([4, 5])
x.append('abc')
print(x)
# gives you
[1, 2, 3, [4, 5], 'abc']
The extend() method takes one argument, a list, and appends each of the items of the argument to the original list. (Lists are implemented as classes. “Creating” a list is really instantiating a class. As such, a list has methods that operate on it.)
x = [1, 2, 3]
x.extend([4, 5])
x.extend('abc')
print(x)
# gives you
[1, 2, 3, 4, 5, 'a', 'b', 'c']
From Dive Into Python.
You can use "+" for returning extend, instead of extending in place.
l1=range(10)
l1+[11]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11]
l2=range(10,1,-1)
l1+l2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 9, 8, 7, 6, 5, 4, 3, 2]
Similarly += for in place behavior, but with slight differences from append & extend. One of the biggest differences of += from append and extend is when it is used in function scopes, see this blog post.
append(object) updates the list by adding the object to the list.
x = [20]
# List passed to the append(object) method is treated as a single object.
x.append([21, 22, 23])
# Hence the resultant list length will be 2
print(x)
--> [20, [21, 22, 23]]
extend(list) concatenates the two lists essentially.
x = [20]
# The parameter passed to extend(list) method is treated as a list.
# Eventually it is two lists being concatenated.
x.extend([21, 22, 23])
# Here the resultant list's length is 4
print(x)
--> [20, 21, 22, 23]
This is the equivalent of append and extend using the + operator:
>>> x = [1,2,3]
>>> x
[1, 2, 3]
>>> x = x + [4,5,6] # Extend
>>> x
[1, 2, 3, 4, 5, 6]
>>> x = x + [[7,8]] # Append
>>> x
[1, 2, 3, 4, 5, 6, [7, 8]]
extend() can be used with an iterator argument. Here is an example. You wish to make a list out of a list of lists this way:
From
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
you want
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
You may use itertools.chain.from_iterable() to do so. This method's output is an iterator. Its implementation is equivalent to
def from_iterable(iterables):
# chain.from_iterable(['ABC', 'DEF']) --> A B C D E F
for it in iterables:
for element in it:
yield element
Back to our example, we can do
import itertools
list2d = [[1,2,3],[4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))
and get the wanted list.
Here is how equivalently extend() can be used with an iterator argument:
merged = []
merged.extend(itertools.chain.from_iterable(list2d))
print(merged)
>>>
[1, 2, 3, 4, 5, 6, 7, 8, 9]
append(): It is basically used in Python to add one element.
Example 1:
>> a = [1, 2, 3, 4]
>> a.append(5)
>> print(a)
>> a = [1, 2, 3, 4, 5]
Example 2:
>> a = [1, 2, 3, 4]
>> a.append([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, [5, 6]]
extend(): Where extend(), is used to merge two lists or insert multiple elements in one list.
Example 1:
>> a = [1, 2, 3, 4]
>> b = [5, 6, 7, 8]
>> a.extend(b)
>> print(a)
>> a = [1, 2, 3, 4, 5, 6, 7, 8]
Example 2:
>> a = [1, 2, 3, 4]
>> a.extend([5, 6])
>> print(a)
>> a = [1, 2, 3, 4, 5, 6]
An interesting point that has been hinted, but not explained, is that extend is faster than append. For any loop that has append inside should be considered to be replaced by list.extend(processed_elements).
Bear in mind that apprending new elements might result in the realloaction of the whole list to a better location in memory. If this is done several times because we are appending 1 element at a time, overall performance suffers. In this sense, list.extend is analogous to "".join(stringlist).
Append adds the entire data at once. The whole data will be added to the newly created index. On the other hand, extend, as it name suggests, extends the current array.
For example
list1 = [123, 456, 678]
list2 = [111, 222]
With append we get:
result = [123, 456, 678, [111, 222]]
While on extend we get:
result = [123, 456, 678, 111, 222]
An English dictionary defines the words append and extend as:
append: add (something) to the end of a written document.
extend: make larger. Enlarge or expand
With that knowledge, now let's understand
1) The difference between append and extend
append:
Appends any Python object as-is to the end of the list (i.e. as a
the last element in the list).
The resulting list may be nested and contain heterogeneous elements (i.e. list, string, tuple, dictionary, set, etc.)
extend:
Accepts any iterable as its argument and makes the list larger.
The resulting list is always one-dimensional list (i.e. no nesting) and it may contain heterogeneous elements in it (e.g. characters, integers, float) as a result of applying list(iterable).
2) Similarity between append and extend
Both take exactly one argument.
Both modify the list in-place.
As a result, both returns None.
Example
lis = [1, 2, 3]
# 'extend' is equivalent to this
lis = lis + list(iterable)
# 'append' simply appends its argument as the last element to the list
# as long as the argument is a valid Python object
list.append(object)
I hope I can make a useful supplement to this question. If your list stores a specific type object, for example Info, here is a situation that extend method is not suitable: In a for loop and and generating an Info object every time and using extend to store it into your list, it will fail. The exception is like below:
TypeError: 'Info' object is not iterable
But if you use the append method, the result is OK. Because every time using the extend method, it will always treat it as a list or any other collection type, iterate it, and place it after the previous list. A specific object can not be iterated, obviously.
To distinguish them intuitively
l1 = ['a', 'b', 'c']
l2 = ['d', 'e', 'f']
l1.append(l2)
l1
['a', 'b', 'c', ['d', 'e', 'f']]
It's like l1 reproduce a body inside her body(nested).
# Reset l1 = ['a', 'b', 'c']
l1.extend(l2)
l1
['a', 'b', 'c', 'd', 'e', 'f']
It's like that two separated individuals get married and construct an united family.
Besides I make an exhaustive cheatsheet of all list's methods for your reference.
list_methods = {'Add': {'extend', 'append', 'insert'},
'Remove': {'pop', 'remove', 'clear'}
'Sort': {'reverse', 'sort'},
'Search': {'count', 'index'},
'Copy': {'copy'},
}
extend(L) extends the list by appending all the items in the given list L.
>>> a
[1, 2, 3]
a.extend([4]) #is eqivalent of a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
a = [1, 2, 3]
>>> a
[1, 2, 3]
>>> a[len(a):] = [4]
>>> a
[1, 2, 3, 4]
append "extends" the list (in place) by only one item, the single object passed (as argument).
extend "extends" the list (in place) by as many items as the object passed (as argument) contains.
This may be slightly confusing for str objects.
If you pass a string as argument:
append will add a single string item at the end but
extend will add as many "single" 'str' items as the length of that string.
If you pass a list of strings as argument:
append will still add a single 'list' item at the end and
extend will add as many 'list' items as the length of the passed list.
def append_o(a_list, element):
a_list.append(element)
print('append:', end = ' ')
for item in a_list:
print(item, end = ',')
print()
def extend_o(a_list, element):
a_list.extend(element)
print('extend:', end = ' ')
for item in a_list:
print(item, end = ',')
print()
append_o(['ab'],'cd')
extend_o(['ab'],'cd')
append_o(['ab'],['cd', 'ef'])
extend_o(['ab'],['cd', 'ef'])
append_o(['ab'],['cd'])
extend_o(['ab'],['cd'])
produces:
append: ab,cd,
extend: ab,c,d,
append: ab,['cd', 'ef'],
extend: ab,cd,ef,
append: ab,['cd'],
extend: ab,cd,
Append and extend are one of the extensibility mechanisms in python.
Append: Adds an element to the end of the list.
my_list = [1,2,3,4]
To add a new element to the list, we can use append method in the following way.
my_list.append(5)
The default location that the new element will be added is always in the (length+1) position.
Insert: The insert method was used to overcome the limitations of append. With insert, we can explicitly define the exact position we want our new element to be inserted at.
Method descriptor of insert(index, object). It takes two arguments, first being the index we want to insert our element and second the element itself.
Example: my_list = [1,2,3,4]
my_list[4, 'a']
my_list
[1,2,3,4,'a']
Extend: This is very useful when we want to join two or more lists into a single list. Without extend, if we want to join two lists, the resulting object will contain a list of lists.
a = [1,2]
b = [3]
a.append(b)
print (a)
[1,2,[3]]
If we try to access the element at pos 2, we get a list ([3]), instead of the element. To join two lists, we'll have to use append.
a = [1,2]
b = [3]
a.extend(b)
print (a)
[1,2,3]
To join multiple lists
a = [1]
b = [2]
c = [3]
a.extend(b+c)
print (a)
[1,2,3]

Categories