Container types are used to group objects together. The main difference between the different container types is the way individual elements are accessed and how operations are defined.
A list is, as the name hints, a list of objects of any kind:
L = ['a' 20.0, 5] M = [3,['a', -3.0, 5]]
The individual objects are enumerated by assigning each element an index. The first element in the list gets index 0. This zero-based indexing is frequently used in mathematical notation. Consider the usual indexing of coefficients of a polynomial.
The index allows us to access the following objects:
L[1] # returns 20.0 L[0] # returns 'a' M[1] # returns ['a',-3.0,5] M[1][2] # returns 5
The bracket notation here corresponds to the use of subscripts in mathematical formulas. L
is a simple list, while M
itself contains a list so that one needs two indexes to access an element of the inner list.
A list containing subsequent integers can easily be generated by the command range
:
L=list(range(4)) # generates a list with four elements: [0, 1, 2 ,3]
A more general use is to provide this command with start, stop, and step parameters:
L=list(range(17,29,4)) # generates [17, 21, 25]
The command len
returns the length of the list:
len(L) # returns 3
Slicing a list between i
and j
creates a new list containing the elements starting at index i
and ending just before j
.
For slicing, a range of indexes has to be given. L[i:j]
means create a list by taking all elements from L
starting at L[i]
until L[j-1]
. In other words, the new list is obtained by removing the first i
elements from L
and taking the next j-i
elements (for j > i ≥ 0). See the following figure (Figure 3.1) for more examples:
Figure 3.1: Some typical slicing situations
Here, L[i:]
means remove the i first elements, L[:i]
means take only the first i elements, and similarly, L[:-i]
means remove the last i elements, and L[-i:]
means take only the last i elements. This may be combined in L[i:-j]
to remove the first i and the last j elements:
L = ['C', 'l', 'o', 'u', 'd', 's'] L[1:5] # remove one element and take four from there: # returns ['l', 'o', 'u', 'd']
One may omit the first or last bound of the slicing:
L = ['C', 'l', 'o', 'u','d', 's'] L[1:] # ['l', 'o', 'u', 'd','s'] L[:5] # ['C', 'l', 'o','u','d'] L[:] # the entire list
Python allows the use of negative indexes for counting from the right. In particular, the element L[-1]
is the last element in the list L
.
Some list indexing descriptions:
L[i:]
amounts to taking all elements except the i first onesL[:i]
amounts to taking the first i elementsL[-i:]
amounts to taking the last i elementsL[:-i]
amounts to taking all elements except the i last onesHere is an example:
L = ['C', 'l', 'o', 'u', 'd', 's'] L[-2:] # ['d', 's'] L[:-2] # ['C', 'l', 'o','u']
Omitting one index in the range corresponds to half-open intervals in ℝ. The half-open interval (∞, a) means, take all numbers strictly lower than a; this is similar to the syntax L[:j]
.
Here is an example:
L = list(range(4)) # [0, 1, 2, 3] L[4] # IndexError: list index out of range L[1:100] # same as L[1:] L[-100:-1] # same as L[:-1] L[-100:100] # same as L[:] L[5:0] # empty list [] L[-2:2] # empty list []
Be careful when using variables in indexing that may become negative, since it changes the slice completely. This might lead to unexpected results:
a = [1,2,3] for iteration in range(4): print(sum(a[0:iteration-1]))
The result is 3
, 0
, 1
, 3
while one expects 0
, 0
, 1
, 3
.
When computing slices, one may also specify a stride, which is the length of the step from one index to the other. The default stride is one. Here is an example:
L = list(range(100)) L[:10:2] # [0, 2, 4, 6, 8] L[::20] # [0, 20, 40, 60, 80] L[10:20:3] # [10, 13, 16, 19]
Note that the stride may also be negative:
L[20:10:-3] # [20, 17, 14, 11]
It is also possible to create a new list that is reversed, using a negative stride (find about reverse method in section In-place operations):
L = [1, 2, 3] R = L[::-1] # L is not modified R # [3, 2, 1]
Typical operations on lists are insertion and deletion of elements and list concatenation. With the slicing notation, list insertion and deletion become obvious; deletion is just replacing a part of a list by an empty list []
:
L = ['a', 1, 2, 3, 4] L[2:3] = [] # ['a', 1, 3, 4] L[3:] = [] # ['a', 1, 3]
Insertion means replacing an empty slice with the list to be inserted:
L[1:1] = [1000, 2000] # ['a', 1000, 2000, 1, 3]
Two lists are concatenated by the plus operator +
:
L = [1, -17] M = [-23.5, 18.3, 5.0] L + M # gives [1, -17, 23.5, 18.3, 5.0]
Concatenating a list n
times with itself motivates the use of the multiplication operator *
:
n = 3 n * [1.,17,3] # gives [1., 17, 3, 1., 17, 3, 1., 17, 3] [0] * 5 # gives [0,0,0,0,0]
There is no arithmetic operations on list, such as elementwise summation or division. For such operations we use arrays (refer to section Array).
One may use the keywords in
and not in
to determine whether an element belongs to a list or not which is similar to and in mathematics:
L = ['a', 1, 'b', 2] 'a' in L # True 3 in L # False 4 not in L # True
Some useful methods of the list
type are collected in the following Table 3.1:
Command |
Action |
|
Add |
|
Expand the list by the elements of the list |
|
Insert |
|
Remove the first item from the list whose value is |
|
The number of times |
|
Sort the items of the list, in place. |
|
Reverse the elements of the list, in place. |
|
Remove the last element of the list, in place. |
Table 3.1: Methods of the datatype list
There are two ways list methods can act:
All methods that result in a list are in-place operating methods, for example, reverse
:
L = [1, 2, 3] L.reverse() # the list L is now reversed L # [3, 2, 1]
Be aware of in-place operations. One might be tempted to write:
L=[3, 4, 4, 5] newL = L.sort()
This is correct Python. But it results in a possibly unintended alternation of L
in a variable newL
having the value None
. The reason is that sort
operates in-place.
Here we demonstrate in-place operating methods:
L = [0, 1, 2, 3, 4] L.append(5) # [0, 1, 2, 3, 4, 5] L.reverse() # [5, 4, 3, 2, 1, 0] L.sort() # [0, 1, 2, 3, 4, 5] L.remove(0) # [1, 2, 3, 4, 5] L.pop() # [1, 2, 3, 4] L.pop() # [1, 2, 3] L.extend(['a','b','c']) # [1, 2, 3, 'a', 'b', 'c']
L
is altered. The count
method is an example of a method that generates a new object:
L.count(2) # returns 1
A particularly useful function for lists is zip
. It can be used to merge two given lists into a new list by pairing the elements of the original lists. The result is a list of tuples (refer section Tuples for more information):
ind = [0,1,2,3,4] color = ["red", "green", "blue", "alpha"] list(zip(color,ind)) # gives [('red', 0), ('green', 1), ('blue', 2), ('alpha', 3)]
This example also demonstrates what happens if the lists have different lengths. The length of the zipped list is the shorter of the two input lists.
zip
creates a special iterable object that can be turned into a list by applying the list
function, as in the preceding example. Refer to section Iterators in Chapter 9, Iterating, for more details on iterable objects.
A convenient way to build up lists is by using the list comprehension construct, possibly with a condition inside. The syntax of a list comprehension is:
[<expr> for <variable> in <list>]
or more generally:
[<expr> for <variable> in <list> if <condition>]
Here is an example:
L = [2, 3, 10, 1, 5] L2 = [x*2 for x in L] # [4, 6, 20, 2, 10] L3 = [x*2 for x in L if 4 < x <= 10] # [20, 10]
It is possible to have several for
loops inside a list comprehension:
M = [[1,2,3],[4,5,6]] flat = [M[i][j] for i in range(2) for j in range(3)] # returns [1, 2, 3, 4, 5, 6]
This is of particular interest when dealing with arrays.
18.220.237.24