Python Programming/Lists
A list in Python is an ordered sequence of items (or elements). It is a very general structure, and list elements don't have to be of the same type: you can put numbers, letters, strings and nested lists all on the same list.
Contents
Overview[edit]
Lists in Python at a glance:
list1 = [] # A new empty list list2 = [1, 2, 3, "cat"] # A new non-empty list with mixed item types list1.append("cat") # Add a single member, at the end of the list list1.extend(["dog", "mouse"]) # Add several members if "cat" in list1: # Membership test list1.remove("cat") # Remove an element from a list #list1.remove("elephant") - throws an error for item in list1: # iterate over a list, step through its elements print (item) print ("Item count:", len(list1)) # get the number of list elements set1 = set(["cat", "dog"]) # Initialize a set from a list list3 = list(set1) # Get a list from a set list4 = list3[:] # A shallow list copy list3 == list4 # True; equality check by value list3 is list4 # False; identity check del list4[:] # Clear the contents of a list print (list1, list2, list3, list4) print (list3[1:3], list3[1:], list3[:2]) # Slices print (max(list3), min(list3), sum(list3)) # Aggregates
List creation[edit]
There are two different ways to make a list in Python. The first is through assignment ("statically"), the second is using list comprehensions ("actively").
Plain creation[edit]
To make a static list of items, write them between square brackets. For example:
[1, 2, 3, "This is a list", 'c', Donkey("kong")]
Observations:
- The list contains items of different data types: integer, string, and Donkey class.
- Objects can be created 'on the fly' and added to lists. The last item is a new instance of Donkey class.
Creation of a new list whose members are constructed from non-literal expressions:
a = 2 b = 3 myList = [a+b, b+a, len(["a","b"])]
List comprehensions[edit]
See also Tips and Tricks
Using list comprehension, you describe the process under which the list should be created. To do that, the list is broken into two pieces. The first is a picture of what each element will look like, and the second is what you do to get it.
For instance, let's say we have a list of words:
>>> listOfWords = ["this","is","a","list","of","words"]
To take the first letter of each word and make a list out of it using list comprehension, we can do this:
>>> items = [word[0] for word in listOfWords] >>> items ['t', 'i', 'a', 'l', 'o', 'w']
List comprehension supports more than one for statement. It will evaluate the items in all of the objects sequentially and will loop over the shorter objects if one object is longer than the rest.
>>> items = [x+y for x in 'cat' for y in 'pot'] >>> items ['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'to', 'tt']
List comprehension supports an if statement, to only include elements into the list that fulfill a certain condition:
>>> [x+y for x in 'cat' for y in 'pot' if x != 't' and y != 'o'] ['cp', 'ct', 'ap', 'at'] >>> [x+y for x in 'cat' for y in 'pot' if x != 't' or y != 'o'] ['cp', 'co', 'ct', 'ap', 'ao', 'at', 'tp', 'tt']
In version 2.x, Python's list comprehension does not define a scope. Any variables that are bound in an evaluation remain bound to whatever they were last bound to when the evaluation was completed. In version 3.x Python's list comprehension uses local variables:
>>> print (x, y) # x and y remember their last values in Python 2 r t >>> print (x, y) # x and y existed only inside the comprehension in Python 3 NameError: name 'x' is not defined
List creation shortcuts[edit]
You can initialize a list to a size, with an initial value for each element:
>>> zeros = [0] * 5 >>> zeros [0, 0, 0, 0, 0]
This works for any data type:
>>> foos = ['foo'] * 3 >>> foos ['foo', 'foo', 'foo']
But there is a caveat. When building a new list by multiplying, Python copies each item by reference. This poses a problem for mutable items, for instance in a multidimensional array where each element is itself a list. You'd guess that the easy way to generate a two dimensional array would be:
listoflists = [[0] * 4] * 5
and this works, but probably doesn't do what you expect:
>>> listoflists [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] >>> listoflists[0][2] = 1 >>> listoflists [[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0]]
What's happening here is that Python is using the same reference to the inner list as the elements of the outer list. Another way of looking at this issue is to examine how Python sees the above definition:
>>> innerlist = [0] * 4 >>> listoflists = [innerlist] * 5 >>> listoflists [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] >>> innerlist[2] = 1 >>> listoflists [[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0]]
Assuming the above effect is not what you intend, one way around this issue is to use list comprehensions:
>>> listoflists = [[0]*4 for i in range(5)] >>> listoflists [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] >>> listoflists[0][2] = 1 >>> listoflists [[0, 0, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Combining lists[edit]
Lists can be combined in several ways. The easiest is just to 'add' them. For instance:
>>> [1,2] + [3,4] [1, 2, 3, 4]
Another way to combine lists is with extend. If you need to combine lists inside of a lambda, extend is the way to go.
>>> a = [1,2,3] >>> b = [4,5,6] >>> a.extend(b) >>> a [1, 2, 3, 4, 5, 6]
The other way to append a value to a list is to use append. For example:
>>> p=[1,2] >>> p.append([3,4]) >>> p [1, 2, [3, 4]]
However, [3,4] is an element of the list, and not part of the list. append always adds one element only to the end of a list. So if the intention was to concatenate two lists, always use extend.
Getting pieces of lists (slices)[edit]
Continuous slices[edit]
Like all sequences in Python, lists can be indexed and sliced.
>>> list = [2, 4, "usurp", 9.0, "n"] >>> list[2] 'usurp' >>> list[3:] [9.0, 'n']
Much like the slice of a string is a substring, the slice of a list is a list. However, lists differ from strings in that we can assign new values to the items in a list.
>>> list[1] = 17 >>> list [2, 17, 'usurp', 9.0, 'n']
We can even assign new values to slices of the lists, which don't even have to be the same length
>>> list[1:4] = ["opportunistic", "elk"] >>> list [2, 'opportunistic', 'elk', 'n']
It's even possible to append things onto the end of lists by assigning to an empty slice:
>>> list[:0] = [3.14,2.71] >>> list [3.14, 2.71, 2, 'opportunistic', 'elk', 'n']
You can also completely change contents of a list:
>>> list[:] = ['new', 'list', 'contents'] >>> list ['new', 'list', 'contents']
On the right-hand side of assignment statement can be any iterable type:
>>> list[:2] = ('element',('t',),[]) >>> list ['element', ('t',), [], 'contents']
With slicing you can create copy of list because slice returns a new list:
>>> original = [1, 'element', []] >>> list_copy = original[:] >>> list_copy [1, 'element', []] >>> list_copy.append('new element') >>> list_copy [1, 'element', [], 'new element'] >>> original [1, 'element', []]
but this is shallow copy and contains references to elements from original list, so be careful with mutable types:
>>> list_copy[2].append('something') >>> original [1, 'element', ['something']]
Non-Continuous slices[edit]
It is also possible to get non-continuous parts of an array. If one wanted to get every n-th occurrence of a list, one would use the :: operator. The syntax is a:b:n where a and b are the start and end of the slice to be operated upon.
>>> list = [i for i in range(10)] >>> list [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> list[::2] [0, 2, 4, 6, 8] >>> list[1:7:2] [1, 3, 5]
Comparing lists[edit]
Lists can be compared for equality.
>>> [1,2] == [1,2] True >>> [1,2] == [3,4] False
Lists can be compared using a less-than operator, which uses lexicographical order:
>>> [1,2] < [2,1] True >>> [2,2] < [2,1] False >>> ["a","b"] < ["b","a"] True
Sorting lists[edit]
Sorting lists is easy with the sort method.
>>> list = [2, 3, 1, 'a', 'b'] >>> list.sort() >>> list [1, 2, 3, 'a', 'b']
Note that the list is sorted in place, and the sort() method returns None to emphasize this side effect.
If you use Python 2.4 or higher there are some more sort parameters:
sort(cmp,key,reverse)
cmp : method to be used for sorting key : function to be executed with key element. List is sorted by return-value of the function reverse : sort(reverse=True) or sort(reverse=False)
Python also includes a sorted() function.
>>> list = [5, 2, 3, 'q', 'p'] >>> sorted(list) [2, 3, 5, 'p', 'q'] >>> list [5, 2, 3, 'q', 'p']
Note that unlike the sort() method, sorted(list) does not sort the list in place, but instead returns the sorted list. The sorted() function, like the sort() method also accepts the reverse parameter.
Iteration[edit]
Iteration over lists:
Read-only iteration over a list, AKA for each element of the list:
list1 = [1, 2, 3, 4] for item in list1: print (item)
For each element of a list satisfying a condition (filtering):
for item in list: if condition(item): print (item)
See also Python Programming/Loops#For_Loops.
Removing[edit]
Removing aka deleting an item at an index (see also #pop(i)):
list = [1, 2, 3, 4] list.pop() # Remove the last item list.pop(0) # Remove the first item , which is the item at index 0 print (list) list = [1, 2, 3, 4] del list[1] # Remove the 2nd element; an alternative to list.pop(1) print (list)
Removing an element by value:
list = ["a", "a", "b"] list.remove("a") # Removes only the 1st occurrence of "a" print (list)
Keeping only items in a list satisfying a condition, and thus removing the items that do not satisfy it:
list = [1, 2, 3, 4] newlist = [item for item in list if item >2] print newlist
This uses a list comprehension.
Aggregates[edit]
There are some built-in functions for arithmetic aggregates over lists. These include minimum, maximum, and sum:
list = [1, 2, 3, 4] print (max(list), min(list), sum(list)) average = sum(list) / float(len(list)) # Provided the list is non-empty # The float() above ensures the division is a float one rather than integer one. print (average)
The max and min functions also apply to lists of strings, returning maximum and minimum with respect to alphabetical order:
list = ["aa", "ab"] print (max(list), min(list)) # Prints "ab aa"
Copying[edit]
Copying AKA cloning of lists:
Making a shallow copy:
list1= [1, 'element'] list2 = list1[:] # Copy using "[:]" list2[0] = 2 # Only affects list2, not list1 print (list1[0]) # Displays 1 # By contrast list1 = [1, 'element'] list2 = list1 list2[0] = 2 # Modifies the original list print (list1[0]) # Displays 2
The above does not make a deep copy, which has the following consequence:
list1 = [1, [2, 3]] # Notice the second item being a nested list list2 = list1[:] # A shallow copy list2[1][0] = 4 # Modifies the 2nd item of list1 as well print (list1[1][0]) # Displays 4 rather than 2
Making a deep copy:
import copy list1 = [1, [2, 3]] # Notice the second item being a nested list list2 = copy.deepcopy(list1) # A deep copy list2[1][0] = 4 # Leaves the 2nd item of list1 unmodified print (list1[1][0]) # Displays 2
See also #Continuous slices.
Links:
- 8.17. copy — Shallow and deep copy operations at docs.python.org
Clearing[edit]
Clearing a list:
del list1[:] # Clear a list list1 = [] # Not really clear but rather assign to a new empty list
Clearing using a proper approach makes a difference when the list is passed as an argument:
def workingClear(ilist): del ilist[:] def brokenClear(ilist): ilist = [] # Lets ilist point to a new list, losing the reference to the argument list list1=[1, 2]; workingClear(list1); print (list1) list1=[1, 2]; brokenClear(list1); print (list1)
Keywords: emptying a list, erasing a list, clear a list, empty a list, erase a list.
List methods[edit]
append(x)[edit]
Add item x onto the end of the list.
>>> list = [1, 2, 3] >>> list.append(4) >>> list [1, 2, 3, 4]
See pop(i)
pop(i)[edit]
Remove the item in the list at the index i and return it. If i is not given, remove the the last item in the list and return it.
>>> list = [1, 2, 3, 4] >>> a = list.pop(0) >>> list [2, 3, 4] >>> a 1 >>> b = list.pop() >>>list [2, 3] >>> b 4
operators[edit]
in[edit]
The operator 'in' is used for two purposes; either to iterate over every item in a list in a for loop, or to check if a value is in a list returning true or false.
>>> list = [1, 2, 3, 4] >>> if 3 in list: >>> .... >>> l = [0, 1, 2, 3, 4] >>> 3 in l True >>> 18 in l False >>>for x in l: >>> print (x) 0 1 2 3 4
Subclassing[edit]
In a modern version of Python [which one?], there is a class called 'list'. You can make your own subclass of it, and determine list behaviour which is different from the default standard.
Exercises[edit]
- Use a list comprehension to construct the list ['ab', 'ac', 'ad', 'bb', 'bc', 'bd'].
- Use a slice on the above list to construct the list ['ab', 'ad', 'bc'].
- Use a list comprehension to construct the list ['1a', '2a', '3a', '4a'].
- Simultaneously remove the element '2a' from the above list and print it.
- Copy the above list and add '2a' back into the list such that the original is still missing it.
- Use a list comprehension to construct the list ['abe', 'abf', 'ace', 'acf', 'ade', 'adf', 'bbe', 'bbf', 'bce', 'bcf', 'bde', 'bdf']
External links[edit]
- Python documentation, chapter "Sequence Types" -- python.org
- Python Tutorial, chapter "Lists" -- python.org