Lists

One of Python's most useful built-in types. It may look like an array from other languages, but it is a whole lot more.

A List is a Sequence

The easiest way to create a list is with the square brackets ([]).

Lists are Mutable

Unlike a string, a list is mutable. Use the [] operator with an index to access an item.

State diagram

It is helpful to visualize how objects relate to memory. Recall that in Python everything is an object that refers to a memory location.

A state diagram is useful in describing or visualizing this binding.

Take a look at the state diagram for our four lists, nums, names, mixed and empty. Notice the box representation of a list and the items within.

state diagram

Negative index

You could also use a negative index to access an item.

The in operator

The in operator also works with lists.

Traversing a List

The most common way to traverse a list is with a for loop.

Note that nested lists are still considered a single element.

len() and range()

Updating the elements of a list requires the index, so one way to do this is using the range() and len() functions.

List Operations

The + concatenates lists:

The * operator repeats a list a given number of times:

List Slices

The slice operator : also works on lists:

The slice returns a copy of the list.

A slice can appear on the left of an assignment operator, since lists are mutable:

List Methods

Let's look at some useful list methods.

.append()

The .append() method appends a new element to the end of a list.

.insert()

The .insert() method allows you to insert an element into the list at a given index.

.extend()

The .extend() method appends a source list to the end of a target list. The source list remains unaffected.

.sort()

The .sort() method orders the elements of a list from low to high.

.reverse()

The .reverse() method reverses the elements of a list.

All the methods that update a list, return None.

Reduce, Map, and Filter

These terms refer to actions or operations performed on lists.

Reduce

An operation that results in a single value is referred to as a reduce operation.

Let's look at how we can compute the sum of a list of numbers.

The sum of all the elements in the list has been reduced to a single value, total. This is such a common operation that Python offers the sum() function to sum the elements of a sequence.

Map

A map transforms one list into another by applying some change to the elements.

Suppose we want to create a new list by traversing a list of strings and changing each one to its uppercase equivalent.

Filter

The selection of a sublist based on some criteria is called a filter operation.

Suppose you want to create a new list that consists of only the odd numbers given a list of numbers.

Deleting Elements

There are several ways to delete elements from a list.

.pop()

If you know the index of the element to delete, then you can use the .pop() method. If no index is provided the last element is deleted.

The method returns the element removed.

del operator

If you are not interested in the removed element, use del instead.

delete a single element

delete some elements with a slice

delete all the elements with a slice

delete the entire list

Careful with this since deleting the list itself is not the same as deleting all the elements of the list.

Deleting the list makes it inaccessible.

.remove()

If you know the element you want to remove rather than its index, use .remove().

Lists and Strings

A string is a sequence of characters and a list is a sequence of values.

list()

A list of characters is not the same as a string however. To convert a string to a list of characters, use list().

.split()

If you want to break a string into words, use .split(). Without an argument it separates each word by using a space as the delimiter.

.join()

If you have a list of words and would like to join them together into a string, use .join().

Since this is a string method, the string object to use is the delimiter that is used to stitch the words back together.

Objects and Values

A string object has a value namely the sequence of characters that make it up.

A list is also an object whose value is the sequence of elements it holds.

Thus, an object is thought of as having a value.

Identical

Variables are references to objects, so:

Two objects are said to be identical if they both refer to the same value in memory.

Use the is operator to find out if the objects are identical.

Why is s1 identical to s2, but l1 is not identical to l2?

The answer lies in the fact that strings are immutable and lists are not. Since a string cannot be mutated, an optimization is made by having both objects refer to the same memory.

Equivalent

Identity is a characteristic of the objects, but equivalence is a characteristic of their values.

Two objects are equivalent is they both hold the same value.

In our example above, the strings are equivalent and identical, while the lists are equivalent, but not identical.

Identical implies equivalent, but equivalent does not imply identical.

The state diagram for the string and list objects is:

identity equivalent state diagram

Aliasing

If a refers to an object and you assign a to b, b = a, then both variables refer to the same object.

The state diagram looks like this:

aliasing

The association of a variable with an object is called a reference. In this example, there are two references to the same object.

If the aliased object is mutable, changes made to one will affect the other.

Aliasing can come in handy at times, but is very error-prone, so be careful using it with mutable objects.

List Arguments

When you pass a list to a function, the function receives a reference to the list, not a copy. If the function changes the list, the caller will see those changes.

Let's look at an example:

Let's take a look at the stack diagram and see what actually takes place in memory.

delete head stack diagram

In __main__, i.e. the script module, the variable letters refers to the list object with value ['a', 'b', 'c']. This reference is then passed to the function deleteHead and copied into the parameter lst. Make sure you reread this carefully and understand that the reference is copied, not the object. This in effect creates an alias to the same object.

Be mindful of operations that update a list and ones that create a new list.

For example the .append() updates while the + creates a list.

This distinction is rather important to remember, since unexpected (mostly bad) things can happen.

Arguments are always passed by value

Remember that arguments are always passed by value, so if you assign a new object to a parameter, the argument object is not affected.

Look at this version of a bad delete head.

An alternative is to return a new list with the desired modifications and assign it to the original list.

Here's an example:

List comprehensions

When creating lists we can use a list comprehension to quickly populate the list.

A list comprehension consists of brackets ([]) containing an expression followed by a for clause, then zero or more for or if clauses.

[expression for element in list if conditional]

Let's see some examples.

The first creates a list of integers using the range() function to generate the desired sequence of numbers. Each element e is assigned to each generated number in turn and added to the list.

The next creates a list of squares.

The next creates a list of just the odd squares.

Our last example creates a list of lists. Each nested list is made up of two elements ([1, 2]) and the outer list is made up of three such lists to produce a two-dimesional list.

Practice problems

Create a separate Python source file (.py) in VSC to complete each exercise.


p1: nestedSum.py

Write a function called nestedSum() that takes a list of integers and adds up the elements from all of the nested lists and returns their sum.

For example:

l = [[1, 2], [3], [4, 5, 6]]
print(nestedSum(l))

Output:

21

p2: cumulativeSum.py

Write a function called cumulativeSum() that takes a list of numbers and returns the cumulative sum; that is, a new list where the $i$th element is the sum of the first $i+1$ elements from the original list.

For example:

l = [1, 2, 3]
print(cumulativeSum(l))

Output:

[1, 3, 6]

p3: middle.py

Write a function called middle() that takes a list and returns a new list that contains all but the first and last elements.

For example:

l = [1, 2, 3, 4]
print(middle(l))

Output:

[2, 3]

p4: chop.py

Write a function called chop() that takes a list, modifies it by removing the first and last elements, and returns None.

For example:

l = [1, 2, 3, 4]
chop(t)
print(l)

Output:

[2, 3]

p5: isSorted.py

Write a function called isSorted() that takes a list as a parameter and returns True if the list is sorted in ascending order and False otherwise.

For example:

print(isSorted([1, 2, 2]))
print(isSorted(['b', 'a']))

Output:

True
False

p6: isAnagram.py

Two words are anagrams if you can rearrange the letters from one to spell the other. Write a function called isAnagram() that takes two strings and returns True if they are anagrams.


p7: hasDuplicates.py

Write a function called hasDuplicates() that takes a list and returns True if there is any element that appears more than once. It should not modify the original list.


p8: buildWords.py

Write a function buildWords() that reads the file words.txt and builds a list with one element per word. Write two versions of this function, one using the .append() method and the other using the idiom t = t + [x].

Which one takes longer to run? Why?


p9: interlockedWords.py

Two words interlock if taking alternating letters from each forms a new word. For example, shoe and cold interlock to form schooled.

Write a program that finds all pairs of words that interlock. Hint: don't enumerate all pairs!

To check whether a word is in the word list, you could use the in operator, but it would be slow because it searches through the words in order.

Instead, since the word list is ordered, use a binary search. Alternatively you can search the Python docs for the bisect module and use that.

[Word Play Case Study] [TOC] [Dictionaries]