This chapter is full of new things. Hang in there! If anything doesn't make sense now, don't worry: What we explain now will teach you important things we will use in another lesson.
Try each example in this lesson; what Python prints is an important part of the lesson.
Today we will show you how to work with lists. We will use square brackets a lot because that's how lists are created:
numbers = [1, 1, 2, 3, 5, 8, 13]
print(numbers)
A list is a value that can contain many other values.
Just like a string contains a sequence of characters,
a list contains a sequence of anything. Numbers, for example.
And just as we can use the for
loop
to print strings character by character,
we can loop over list elements:
for number in numbers:
print(number)
Lists in programs are very common:
A file can be retrieved as a list of strings
line by line.
A list of strings like 7 ♥
and K ♣
can be used as a deck of cards.
Math is full of numerical lists and
each online service has a list of users.
The values in a list can be of any type, we can even mix different types in one list (even though we won't meet such mixed lists very often - they are more used in tuples, which we will tell you about later):
list = [1, 'abc', True, None, range(10), len]
print(list)
You already know the most basic operation with lists,
the for
loop.
The second most important operation is picking
individual elements.
This works the same way as in strings: square brackets and
the element number. List elements are numbered from zero,
just as characters in strings; negative numbers indicate elements from the end.
print(numbers[2])
We use square brackets to access subsets.
╭───┬───┬───┬───┬───┬───┬───┬───╮
│ P │ y │ L │ a │ d │ i │ e │ s │
├───┼───┼───┼───┼───┼───┼───┼───┤
│ │ │ │ │ │ │ │ │
0 1 2 3 4 5 6 7 8
-8 -7 -6 -5 -4 -3 -2 -1
╰───────────────╯
'PyLadies'[:4] == 'PyLa'
╰───────────────╯
'PyLadies'[2:6] == 'Ladi'
╰───────────╯
'PyLadies'[-3:] == 'ies'
shows you how to write the numbers when you want parts of the list:
print(numbers[2:-3])
An important feature of lists is that neither numbers nor strings
(nor True
/False
/None
) have, is
that lists can be changed (they are mutable).
Numbers can't be changed - if you have a = 3
and
you write a = a + 1
, the number 3
will not change.
A new number 4
will be calculated, and the variable a
will be set to this new number.
By contrast, lists can be changed without setting a variable to a new value.
The most basic way to change a list is to add elements
to its end, using the append
method.
Doing this doesn't return anything (actually it returns None
)
but it changes the list we are working on in place (append
means
add to the end of the list). Try it:
prime_numbers = [2, 3, 5, 7, 11, 13, 17]
print(prime_numbers)
prime_numbers.append(19)
print(prime_numbers)
Such a value change can sometimes be surprising, because multiple variables can have the same value. Because the value itself changes, it may seem that the variable "changes without us touching it":
a = [1, 2, 3] # creates a list 'a'
b = a # no new list is created, 'b' just points to 'a'
# the list created in the first row now has two variable names: "a" and "b",
# but we are still working with just one and the same list:
print(b)
a.append(4)
print(b)
Apart from the append
method that adds
only one element, there is also the extend
method,
which can add more elements.
The elements to be added here are in the form of a list:
more_prime_nr = [23, 29, 31]
prime_numbers.extend(more_prime_nr)
print(prime_numbers)
The extend
method can work with other
types of variables - it can work with anything on which
we can use a for
loop: For example,
individual strings, rows of files, or numbers from range()
.
listA = []
listA.extend('abcdef')
listA.extend(range(10))
print(listA)
But enough adding. You can change individual elements of lists, simply by assigning a value to the element, as if it were a variable:
numbers = [1, 0, 3, 4]
numbers[1] = 2
print(numbers)
You can also assign new values to a sublist - in this case
the subset is replaced by the individual values we write.
Like with extend
, you can replace the elements with anything
that works with for
loops - list, string, range()
, etc.
numbers = [1, 2, 3, 4]
numbers[1:-1] = [6, 5]
print(numbers)
We can also change the length of the list by replacing a sublist with fewer elements, or by removing some of the elements completely:
numbers = [1, 2, 3, 4]
numbers[1:-1] = [0, 0, 0, 0, 0]
print(numbers)
numbers[1:-1] = []
print(numbers)
This form of deleting elements is quite obscure,
therefore we have a special command named del
.
It deletes everything that we tell it to - individual
elements, sublists and even variables!
numbers = [1, 2, 3, 4, 5, 6]
del numbers[-1]
print(numbers)
del numbers[3:5]
print(numbers)
del numbers
print(numbers)
Other deleting methods are:
pop
, which removes and returns the last element in the list - for example, if
I have a list of cards in a deck, pop
is like "drawing a card".remove
, which finds the element in the list and removes it,clear
, which clears the entire list.numbers = [1, 2, 3, 'abc', 4, 5, 6, 12]
last = numbers.pop()
print(last)
print(numbers)
numbers.remove('abc')
print(numbers)
numbers.clear()
print(numbers)
And we also have a sort
method that sorts list elements.
listA = [4, 7, 8, 3, 5, 2, 4, 8, 5]
listA.sort()
print(listA)
In order to be sorted, the elements of the list must be
comparable - we have to be able to use the <
operator with them.
A mixed list of numbers and strings cannot be sorted.
The operator <
defines how exactly the elements will
be sorted (e.g., numbers by size; strings according to the special "alphabet"
where upper case is smaller than lower case, etc.).
The sort
method has a reverse
argument.
If you set it to True, it will sort the elements in backwards order.
The default value is False, so if you want the elements to be
sorted from smaller to larger, you don't have to specify this argument.
listA = [4, 7, 8, 3, 5, 2, 4, 8, 5]
listA.sort(reverse=True)
print(listA)
Lots of what we can do with strings, we can also do with lists. For example adding and multiplying:
melody = ['C', 'E', 'G'] * 2 + ['E', 'E', 'D', 'E', 'F', 'D'] * 2 + ['E', 'D', 'C']
print(melody)
As with strings, the list can be added only to other lists
Other known methods are len
, count
, andindex
,
and the in
operator.
print(len(melody)) # Length of the list
print(melody.count('E')) # How many 'E's are in the list?
print(melodie.index('E')) # Position of the first 'E'
print('E' in melody) # Is 'E' in the list?
The last three methods work a little bit differently:
for strings they are work on substrings,
for lists they work on individual elements.
So although our melody contains the elements
D
and E
next to each other, DE
is not in the list:
print('DE' in melody)
print(melody.count('DE'))
print(melody.index('DE'))
Write a function that returns a middle element of a list.
Write a function which counts how many entries of a list are larger than 10 and smaller than 15:
A list can be used in an if
(orwhile
) statement
which is true while there is something in that list.
In other words, list
is an 'abbreviation' for len(list) > 0
.
if list:
print ('There is something in the list!')
else:
print ('The list is empty!')
Strings can be used similarly. And even numbers - the condition is True if they are not zero.
Just like the int
function converts values to
integers and str
converts values to strings,
the list
function converts values to a list.
As an argument, we can give it any value,
which can be processed by a for
loop.
A string will turn into a list of characters, a file
will turn into a list of rows, a range
will turn
into a list of numbers.
alphabet = list('abcdefghijklmnopqrstuvwxyz')
numbers = list(range(100))
print(alphabet)
print(numbers)
The list
function can also create a list from a list.
It may sound useless, but it isn't - it creates a new list that
is not dependent on the old list.
It will contain the same elements in the same order,
but it will not be the same list:
You can change it independently of the old one.
a = [1, 2, 3]
b = list(a)
print(b)
a.append(4)
print(b)
Another way to create lists
(especially more complex lists) is to first make an empty
list, and then fill it up using the append
function.
For example, if you want a list with numbers that are
powers of two, pass the numbers into a for
loop, and
for each number, add the appropriate power to the list:
power_of_two = []
for number in range (10):
power_of_two.append (2 ** number)
print(power_of_two)
If you want a list that represents a deck of cards,
call append
for all combinations of color and value.
deck = []
for color in '♠', '♥', '♦', '♣': # (Use text names on Windows)
for value in list(range(2, 11)) + ['J', 'Q', 'K', 'A']:
deck.append(str(value) + color)
print(deck)
Lists and strings are types of "sequences",
so it is not surprising that they can be converted
from one type to another.
The list
function creates a list of characters from a string.
If we want to get a list of words, we use the split
method on a sentence:
words = 'This sentence is complex, split it into words!'.split()
print(words)
The split
method can also take an argument.
If we pass it a separator character, the string is "cut"
at this given separator, instead of at spaces (and new lines).
So, when we have some data separated by commas,
there is nothing easier than using split
with a comma argument:
records = '3A, 8B, 2E, 9D'.split(',')
print(records)
If we want to join a list of strings into
a single string, we use the method join
.
Note that this method is called on the delimiter character that we want to use
between the elements of a list, and as an argument, it takes the list.
sentence = ' '.join(words)
print(sentence)
Imagine that users enter their names and surnames, and you store them in a list for future use, for instance, student records. Not all users are careful when entering their names, so the names can appear with incorrectly capitalized letters. For example:
records = ['john doe', 'John Smith', 'Stuart little', 'petr File']
Your task is:
The result should look like this:
records = ['john doe', 'John Smith', 'Stuart little', 'petr File']
error_entries = select_errors(records)
print(error_entries) # → ['john doe', 'Stuart little', 'petr File']
ok_entries = select_correct(records)
print(ok_entries) # → ['John Smith']
corected_entries = correct_entries(records)
print(corected_entries) # → ['John Doe', 'John Smith', 'Stuart Little', 'Petr File']
An easy way to find out if the string is written in lower case,
is the islower()
method, which returns True if the string contains only lower
case letters, otherwise it returns False. For example, 'abc'.islower() == True
but
'aBc'.islower() == False
.
The easiest way to convert first letters to upper case is capitalize()
:
'abc'.capitalize() == 'Abc'
The random
module contains two functions that can be used with lists.
First, the shuffle
function shuffles elements - all elements are left in a random order.
Just like sort
, shuffle
does not return anything.
import random
deck = []
for color in '♠', '♥', '♦', '♣':
for value in list(range(2, 11)) + ['J', 'Q', 'K', 'A']:
deck.append(str(value) + color)
print(deck)
random.shuffle(deck)
print(deck)
The second one is the choice
function that selects a random element from the list.
Using a list, it's much easier to implement rock/paper/scissors:
import random
possibilities = ['rock', 'scissors', 'paper']
pc_choice = random.choice(possibilities)
In the beginning of this lesson we said that a list can contain any type of value. A list can even contain other lists:
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Such a list behaves as expected - we can choose elements (which are, of course, lists):
first_list = list_of_lists[0]
print(first_list)
And since elements are themselves lists, we can talk about elements like "the first element of the second list":
second_list = list_of_lists[1]
first_element_of_second_list = second_list[0]
print(first_element_of_second_list)
And because list_of_lists[1]
indicates the list, we can take the elements directly from it:
first_element_of_second_list = (list_of_lists[1])[0]
Or:
first_element_of_second_list = list_of_lists[1][0]
This approach is quite useful.
Same as nested for
loops
allowed us to list a table, nested lists
allow us to store a table.
def create_tab(size=11):
row_list = []
for a in range(size):
row = []
for b in range(size):
row.append(a * b)
row_list.append(row)
return row_list
multiplication_tab = create_tab()
print(multiplication_tab[2][3]) # two times three
print(multiplication_tab[5][2]) # five times two
print(multiplication_tab[8][7]) # eight times seven
# List the entire table
for row in multiplication_tab:
for number in row:
print(number, end = '')
print()
What can we do with such a stored table? For example, you can save the positions of figures on a chessboard, or of the crosses and circles in a 2D tictactoe.