Lists

A list is a sequential collection of Python data values, where each value is identified by an index. The values that make up a list are called its elements.

Lists are ordered collections of anything. The types of list elements can be of any kind, even other lists.

Creating a list

Closing things in [] square brackets:

[10, 20, 30, 40]
["spam", "bungee", "swallow"]
["hello", 2.0, 5, [10, 20]]         # nested list
[]                                     # empty list
a = ["a", 1]                         # variable holding a list 
print(a)                            # passing list to functions as parameters

A list within another list is said to be nested. The inner list is a sublist.

Length - just the outer!

alist =  ["hello", 2.0, 5, [10, 20]]
print(len(alist))
print(len(['spam!', 1, ['Brie', 'Roquefort', 'Pol le Veq'], [1, 2, 3]]))
>>> 4
>>> 4

Accessing elements

numbers = [17, 123, 87, 34, 66, 8398, 44]
print(numbers[2])
print(numbers[9 - 8])
print(numbers[-2])
print(numbers[len(numbers) - 1])

Just like strings!

list = [1,2,3, [1,2]]

accessing can be chained!

list[3][0]
>>> 1

And just like strings, we can slice.

a_list = ['a', 'b', 'c', 'd', 'e', 'f']
print(a_list[1:3])
print(a_list[:4])
print(a_list[3:])
print(a_list[:])

>>> ['b', 'c']
>>> ['a', 'b', 'c', 'd']
>>> ['d', 'e', 'f']
>>> ['a', 'b', 'c', 'd', 'e', 'f']

in or not in list AKA. List membership

Just like strings:

fruit = ["apple", "orange", "banana", "cherry", [1,2]]

print("apple" in fruit)
print("pear" in fruit)

>>> True
>>> False

BUT only outer list!

print(1 in fruit)
>>> False

Concatenation and Repetition (Multiplication)

fruit = ["apple", "orange", "banana", "cherry"]
print([1, 2] + [3, 4])
>>> [1, 2, 3, 4]

print(fruit + [6, 7, 8, 9])
>>> ['apple', 'orange', 'banana', 'cherry', 6, 7, 8, 9]

print([0] * 4)
>>> [0, 0, 0, 0]

print([1, 2, ["hello", "goodbye"]] * 2)
>>> [1, 2, ['hello', 'goodbye'], 1, 2, ['hello', 'goodbye']]

Memory location

alist = [4, 5, 6]
id(alist)
>>> 140135490300424

MUTABILITY

Unlike strings, lists are mutable.

This means we can change an item in a list by accessing it directly as part of the assignment statement. Using the indexing operator (square brackets) on the left side of an assignment, we can update one of the list items.

An assignment to an element of a list is called item assignment.

Change items

fruit = ["banana", "apple", "cherry"]
fruit[0] = "pear"
print(fruit)

>>> ['pear', 'apple', 'cherry']

Change slice on the go:

alist = ['a', 'b', 'c', 'd', 'e', 'f']
alist[1:3] = ['x', 'y']
print(alist)

>>> ['a', 'x', 'y', 'd', 'e', 'f']

Remove items

We can also remove elements from a list by assigning the empty list to them.

alist = ['a', 'b', 'c', 'd', 'e', 'f']
alist[1:3] = [] # can be used to remove multiple elements
print(alist)

>>> ['a', 'd', 'e', 'f']

Using slices to delete list elements can be awkward and therefore error-prone. Python provides an alternative that is more readable. The del statement removes an element from a list by using its position.

a = ['one', 'two', 'three']
del a[1] # can oly remove one element
print(a)

>>> ['one', 'three']

Alert! del causes a runtime error if the index is out of range. But so does reassignment using [].

Using remove() will remove the first occurrence of the element.

a_list = ['one', 'two', 'three']
a_list.remove("one") # only the first (and one) element

Insert items

alist = ['a', 'd', 'f']
alist[1:1] = ['b', 'c']
print(alist)
alist[4:4] = ['e']
print(alist)

>>> ['a', 'b', 'c', 'd', 'f']
>>> ['a', 'b', 'c', 'd', 'e', 'f']

Clone (copy) list

a = [81, 82, 83]
b = a[:] 
print(a == b)
print(a is b)

>>> True
>>> False

List Methods

mylist = [5, 12, 27, 3, 12]            # [5, 12, 27, 3, 12]
mylist.append(5)                    # [5, 12, 27, 3, 12, 5]
mylist.insert(1, 12)                # [5, 12, 12, 27, 3, 12, 5]
mylist.index(3)                        # 4
mylist.count(5)                        # 2
mylist.reverse()                    # [5, 12, 3, 27, 12, 12, 5]
mylist.sort()                        # [3, 5, 5, 12, 12, 12, 27]
mylist.remove(5)                    # [3, 5, 12, 12, 12, 27]
lastitem = mylist.pop()                # [3,5,12,12,12]
print(lastitem)                        # 27
mylist.extend()

The word mutator means that the list is changed by the method but nothing is returned (actually None is returned). A hybrid method is one that not only changes the list but also returns a value as its result. Finally, if the result is simply a return, then the list is unchanged by the method.

Method

Parameters

Result

Description

append

item

mutator

Adds a new item to the end of a list

insert

position, item

mutator

Inserts a new item at the position given

pop

none

hybrid

Removes and returns the last item

pop

position

hybrid

Removes and returns the item at position

sort

none

mutator

Modifies a list to be sorted

reverse

none

mutator

Modifies a list to be in reverse order

index

item

return idx

Returns the position of first occurrence of item

count

item

return ct

Returns the number of occurrences of item

remove

item

mutator

Removes the first occurrence of item. Must be in, otherwise ValueError appears.

extend

list

mutator

Extends with the elements in the given list

More in documentation

It is important to remember that methods like append, sort, and reverse all return None. Do not use them for reassignment !!!

List traversal

fruits = ["apple", "orange", "banana", "cherry"]

for fruit in fruits:     # by item
    print(fruit)
fruits = ["apple", "orange", "banana", "cherry"]

for position in range(len(fruits)):     # by index
    print(fruits[position])

Since lists are mutable, it is often desirable to traverse a list, modifying each of its elements as you go.

numbers = [1, 2, 3, 4, 5]
print(numbers)

for i in range(len(numbers)):
    numbers[i] = numbers[i] ** 2

print(numbers)

>>> [1, 2, 3, 4, 5]
>>> [1, 4, 9, 16, 25]

Using lists as parameters

Functions which take lists as arguments and change them during execution are called modifiers and the changes they make are called side effects. Passing a list as an argument actually passes a reference to the list, not a copy of the list.

def doubleStuff(aList):
    """ Overwrite each element in aList with double its value. """
    for position in range(len(aList)):
        aList[position] = 2 * aList[position]

things = [2, 5, 9]
print(things)
doubleStuff(things)
print(things)

>>> [2, 5, 9]
>>> [4, 10, 18]

Pure function

A pure function does not produce side effects.

It communicates with the calling program only through parameters (which it does not modify) and a return value.

def doubleStuff(a_list):
    """ Return a new list in which contains doubles of the elements in a_list. """
    new_list = []
    for value in a_list:
        new_elem = 2 * value
        new_list.append(new_elem)
    return new_list

things = [2, 5, 9]
print(things)
things = doubleStuff(things)
print(things)

Functional programming

Anything that can be done with modifiers can also be done with pure functions. In fact, some programming languages only allow pure functions. There is some evidence that programs that use pure functions are faster to develop and less error-prone than programs that use modifiers. Nevertheless, modifiers are convenient at times, and in some cases, functional programs are less efficient.

In general, we recommend that you write pure functions whenever it is reasonable to do so and resort to modifiers only if there is a compelling advantage. This approach might be called a functional programming style.

List Comprehensions

List comprehensions are concise ways to create lists. The general syntax is:

[<expression> for <item> in <sequence> if  <condition>] # if is optional.
mylist = [1,2,3,4,5]
yourlist = [item ** 2 for item in mylist]
print(yourlist)

>>> [1, 4, 9, 16, 25]

using the if clause (assuming you have access to is_prime() function:

[num for num in range(2,n) if is_prime(num)]

List comprehension explained with an example:

Problem: You have to print a list of all possible coordinates given a 3D grid where the sum of x,y,z is != N

for x=y=z=1 and N=2 output: [[0, 0, 0], [0, 0, 1], [0, 1, 0], [1, 0, 0], [1, 1, 1]]

Standard loop solution:

x = 1
y = 1
z = 1
n = 2
grid = []

for a in range(x + 1):
    for b in range(y + 1):
        for c in range(z + 1):
            if a + b + c != n:
                grid.append([a, b, c])
print(grid)
>>> [[0, 0, 0], [0, 0, 1], [0, 1, 0], [1, 0, 0], [1, 1, 1]]

List comprehension solution

x = 1
y = 1
z = 1
n = 2

print([[a,b,c] for a in range(x + 1) for b in range(y + 1) for c in range(z + 1) if a + b + c != n])

Lists and strings conversion LIST<>STRING

You can send iterable things to a list() to turn into a list.

string = "Hello you, how are you?"
string.split()                       # by default breaks on white space
# ['Hello', 'you,', 'how', 'are', 'you?']

"name;age;address".split(";") 
# ["name", "age", "address"]

An optional argument called a delimiter can be used to specify which characters to use as word boundaries. The delimiter does not appear in the results.

song = "The rain in Spain..."
wds = song.split('ai')
print(wds)

>>> ['The r', 'n in Sp', 'n...']

Joining back (after some changes):

wds = ["red", "blue", "green"]
glue = ';'
s = glue.join(wds)
print(s)
print(wds)

print("***".join(wds))
print("".join(wds))

>>> red;blue;green
>>> ['red', 'blue', 'green']
>>> red***blue***green
>>> redbluegreen

You cannot join things that aren't strings. Doing ", ".join(5, 10, 15) will give you an exception.

Type conversion. To list. list()

xs = list("Crunchy Frog")
print(xs)

>>> ['C', 'r', 'u', 'n', 'c', 'h', 'y', ' ', 'F', 'r', 'o', 'g']

It is not legal to use the listconversion function on any argument that is not a sequence.

  • split will break a string into a list of “words”

  • list will always break it into a list of characters

Last updated