6.3. List Operations#

This section covers how to work with lists using

  • operators,

  • built-in functions, and

  • methods.

import sys
from pathlib import Path

# Find project root by looking for _config.yml
current = Path.cwd()
for parent in [current, *current.parents]:
    if (parent / '_config.yml').exists():
        project_root = parent
        break
else:
    project_root = Path.cwd().parent.parent

# Add project root to path
sys.path.insert(0, str(project_root))

# Import shared teaching helpers and cell magics
from shared import thinkpython, diagram, jupyturtle, structshape
from shared.download import download
fruits = ['apple', 'banana', 'cherry']

6.3.1. List Operators#

Python supports several operators that work directly with lists:

Operator

Name

Description

Example

Result

+

Concatenation

Combines two lists

[1, 2] + [3, 4]

[1, 2, 3, 4]

*

Repetition

Repeats a list

[1, 2] * 3

[1, 2, 1, 2, 1, 2]

in

Membership

Checks if item exists in list

3 in [1, 2, 3]

True

not in

Non-membership

Checks if item doesn’t exist

5 not in [1, 2, 3]

True

[]

Indexing

Accesses element by position

[10, 20, 30][0]

10

[:]

Slicing

Extracts portion of list

[0, 1, 2, 3][1:3]

[1, 2]

==

Equality

Checks if lists are equal

[1, 2] == [1, 2]

True

!=

Inequality

Checks if lists are not equal

[1, 2] != [1, 3]

True

<

Less than

Lexicographic comparison

[1, 2] < [1, 3]

True

>

Greater than

Lexicographic comparison

[1, 3] > [1, 2]

True

<=

Less than or equal

Lexicographic comparison

[1, 2] <= [1, 2]

True

>=

Greater than or equal

Lexicographic comparison

[1, 3] >= [1, 2]

True

The + operator concatenates lists.

num1 = [1, 2, 3]
num2 = [4, 5, 6]

num1 + num2
[1, 2, 3, 4, 5, 6]

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

['spam'] * 4
['spam', 'spam', 'spam', 'spam']
### EXERCISE: List Concatenation and Repetition
# 1. Create two lists: list1 = [1, 2, 3] and list2 = [4, 5, 6]
# 2. Concatenate them to create list3
# 3. Create list4 by repeating [0] three times
### Your code starts here:



### Your code ends here.

Hide code cell source

# Solution
list1 = [1, 2, 3]
list2 = [4, 5, 6]
list3 = list1 + list2
list4 = [0] * 3

print(f"List1 + List2: {list3}")
print(f"[0] * 3: {list4}")
List1 + List2: [1, 2, 3, 4, 5, 6]
[0] * 3: [0, 0, 0]

6.3.1.1. Membership Testing#

The in operator checks whether a given element appears anywhere in the list.

'apple' in fruits
True
print('tomato' in fruits)
print('tomato' not in fruits)
False
True

When checking membership with in, only top-level elements are considered. For example, 'spam' is in nested mixed_list, but 10 is not (since it’s inside a nested list):

numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
mixed_list = ['spam', 2.0, 5, numbers ]

print('spam' in mixed_list)     ### True
print(10 in mixed_list)         ### False
True
False
### EXERCISE: Membership Testing
inventory = ['apple', 'banana', 'orange', 'grape', 'mango']
# 1. Check if 'orange' is in the inventory
# 2. Check if 'strawberry' is NOT in the inventory
# 3. Create a list of items to check: ['apple', 'kiwi', 'grape']
#    and count how many of them are in inventory using a 
#    LIST COMPREHENSION and sum()
### Your code starts here:



### Your code ends here.

Hide code cell source

# Solution
inventory = ['apple', 'banana', 'orange', 'grape', 'mango']
has_orange = 'orange' in inventory
no_strawberry = 'strawberry' not in inventory

check_items = ['apple', 'kiwi', 'grape']
count_found = sum( [item in inventory for item in check_items] ) 
### .count(True) is not needed because True is treated as 1 and False as 0 in sum()

print(f"Has orange: {has_orange}")
print(f"No strawberry: {no_strawberry}")
print(f"Items found in inventory: {count_found}")
Has orange: True
No strawberry: True
Items found in inventory: 2

6.3.2. List Methods/Functions#

Python provides many built-in methods and functions that operate on lists. Common list methods and functions include:

Purpose

Function/Method

Description

Example

Result

Creating/Copying

list()

Creates a new list

list("abc")

['a', 'b', 'c']

copy()

Returns shallow copy

[1, 2, 3].copy()

[1, 2, 3] (new list)

Adding Items

append()

Adds single item to end

[1, 2].append(3)

[1, 2, 3]

insert()

Inserts item at position

[1, 3].insert(1, 2)

[1, 2, 3]

extend()

Adds all items from iterable

[1, 2].extend([3, 4])

[1, 2, 3, 4]

Removing Items

remove()

Removes first occurrence of value

[1, 2, 3].remove(2)

[1, 3]

pop()

Removes and returns last item

[1, 2, 3].pop()

Returns 3, list becomes [1, 2]

pop(index)

Removes and returns item at index

[1, 2, 3].pop(0)

Returns 1, list becomes [2, 3]

clear()

Removes all items

[1, 2, 3].clear()

[]

Searching/Counting

index()

Returns index of first occurrence

[1, 2, 3].index(2)

1

count()

Counts occurrences of value

[1, 2, 2, 3].count(2)

2

Sorting/Reversing

sort()

Sorts list in place

[3, 1, 2].sort()

[1, 2, 3]

sorted()

Returns new sorted list

sorted([3, 1, 2])

[1, 2, 3] (original unchanged)

reverse()

Reverses list in place

[1, 2, 3].reverse()

[3, 2, 1]

reversed()

Returns reverse iterator

list(reversed([1, 2, 3]))

[3, 2, 1]

Information/Statistics

len()

Returns number of items

len([1, 2, 3])

3

max()

Returns largest item

max([1, 2, 3])

3

min()

Returns smallest item

min([1, 2, 3])

1

sum()

Returns sum of numeric items

sum([1, 2, 3])

6

Let’s explore some of these with examples:

6.3.2.1. List Functions#

Python provides several built-in functions that work with lists to perform common operations, such as finding the length (len()), maximum (max()), minimum (min()), sum (sum()), sorting (sorted()), and type conversion (list()).

The len function returns the length of a list as the count of number of the elements.

numbers = [1, 2, 3, 4, 5]
fruits = ['apple', 'banana', 'cherry', 'date', 'elderberry']
print(f"There are {len(numbers)} numbers in {numbers}.")
print(f"There are {len(fruits)} fruits in {fruits}.")
There are 5 numbers in [1, 2, 3, 4, 5].
There are 5 fruits in ['apple', 'banana', 'cherry', 'date', 'elderberry'].

The length of an empty list is 0.

empty = []
len(empty)
0

No other mathematical operators work with lists, but the built-in function sum adds up the elements. And the min and max functions find the smallest and largest elements.

num1 = [1, 2, 3]
num2 = [4, 5, 6]

print(sum(num1))
print(min(num1))
print(max(num2))
6
1
6

6.3.3. List Modifying Methods#

Lists have built-in methods that allow you to modify them in place, such as adding, removing, or reordering elements.

letters = ['a', 'b', 'c', 'd']
print(f"Original list:\t\t {letters}")

# append() - Adds element to the end
letters.append('e')
print(f"After append 'e':\t {letters}")

# extend() - Appends all elements from another list
letters.extend(['f', 'g'])
print(f"After extend ['f', 'g']: {letters}")

# insert() - Inserts element at specific position
letters.insert(0, 'z')
print(f"After insert at 0:\t {letters}")

# remove() - Removes first occurrence of element
letters.remove('z')
print(f"After remove 'z':\t {letters}")

# pop() - Removes and returns element at index (or last if no index)
last_item = letters.pop()
print(f"Popped: {last_item}, Remaining:\t {letters}")

# clear() - Removes all elements
temp = [1, 2, 3]
temp.clear()
print(f"After clear:\t\t {temp}")
Original list:		 ['a', 'b', 'c', 'd']
After append 'e':	 ['a', 'b', 'c', 'd', 'e']
After extend ['f', 'g']: ['a', 'b', 'c', 'd', 'e', 'f', 'g']
After insert at 0:	 ['z', 'a', 'b', 'c', 'd', 'e', 'f', 'g']
After remove 'z':	 ['a', 'b', 'c', 'd', 'e', 'f', 'g']
Popped: g, Remaining:	 ['a', 'b', 'c', 'd', 'e', 'f']
After clear:		 []

Note: If you try to remove() an element that doesn’t exist, Python raises a ValueError. If you try to pop() from an empty list, Python raises an IndexError.

6.3.4. Iteration Helpers: enumerate and zip#

Using enumerate()

When looping through a list, you sometimes need to know both the element and its index. The enumerate() function returns pairs of (index, element) for each item in the list.

fruits = ['apple', 'banana', 'cherry']

for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")
0: apple
1: banana
2: cherry

Using zip()

The zip() function is useful when you need to loop through two or more lists in parallel. It pairs up elements from each list and returns tuples.

names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 35]
cities = ['New York', 'London', 'Tokyo']

for name, age, city in zip(names, ages, cities):
    print(f"{name} is {age} years old and lives in {city}")
Alice is 25 years old and lives in New York
Bob is 30 years old and lives in London
Charlie is 35 years old and lives in Tokyo
test = zip(names, ages, cities)
print(test)         # This will print a zip object, not the contents
print(list(test))   # Convert zip object to list to see contents

test2  = zip(names, ages)
print(dict(test2))  # Convert to dict to see contents (keys from names, values from ages)
<zip object at 0x10c7e7000>
[('Alice', 25, 'New York'), ('Bob', 30, 'London'), ('Charlie', 35, 'Tokyo')]
{'Alice': 25, 'Bob': 30, 'Charlie': 35}
### EXERCISE: Using List Methods
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
# 1. Count how many times 1 appears in the list 
# 2. Append the number 7 to the end
# 3. Remove the first occurrence of 1
# 4. Find the index of the number 5
### Your code starts here:



### Your code ends here.

Hide code cell source

# Solution
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
count_ones = numbers.count(1)
print(f"Count of 1s: {count_ones}")
numbers.append(7)
print(f"List after appending 7: {numbers}")
numbers.remove(1)
print(f"List after removing first occurrence of 1: {numbers}")
index_of_five = numbers.index(5)
print(f"Index of 5: {index_of_five}")
Count of 1s: 2
List after appending 7: [3, 1, 4, 1, 5, 9, 2, 6, 7]
List after removing first occurrence of 1: [3, 4, 1, 5, 9, 2, 6, 7]
Index of 5: 3
### EXERCISE: Using enumerate() and zip()
### with the following lists:
fruits = ['apple', 'banana', 'cherry']
prices = [10, 20, 30]
# 1. Use enumerate() to print the index and fruit name 
#    as "0: apple", "1: banana", etc.
# 2. Use zip() to print each fruit with its corresponding price 
#    as "apple costs 10", "banana costs 20", etc.
### Your code starts here:



### Your code ends here.

Hide code cell source

# Solution

fruits = ['apple', 'banana', 'cherry']
prices = [10, 20, 30]

for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")      

for fruit, price in zip(fruits, prices):
    print(f"{fruit} costs {price}")
0: apple
1: banana
2: cherry
apple costs 10
banana costs 20
cherry costs 30

6.3.5. List Unpacking#

Unpacking is a Python feature that allows you to assign multiple values from a list (or any iterable) to multiple variables in a single statement. Instead of accessing elements one by one with indexing, you can extract them all at once.

This makes your code more readable and Pythonic, especially when working with structured data.

6.3.5.1. Basic Unpacking#

# Without unpacking (verbose)
point = [10, 20, 30]
x = point[0]
y = point[1]
z = point[2]
# With unpacking (concise)
point = [10, 20, 30]
x, y, z = point         ### assigns 10 to x, 20 to y, 30 to z
# Unpacking actually works with any iterable

first, second = "hi"
print(f"first={first}, second={second}")
first=h, second=i

6.3.5.2. With Star Operator#

  • Using * (the unpacking operator) allows you to capture multiple elements.

  • You can only have one *variable per unpacking statement.

# Capture the first element and the rest
numbers = [1, 2, 3, 4, 5]
first, *rest = numbers

print(f"First: {first}")
print(f"Rest: {rest}")
First: 1
Rest: [2, 3, 4, 5]
# Capture first, last, and middle
first, *middle, last = numbers
print(f"First: {first}, Middle: {middle}, Last: {last}")
First: 1, Middle: [2, 3, 4], Last: 5
# Capture last element
*most, last = numbers
print(f"Most: {most}, Last: {last}")
Most: [1, 2, 3, 4], Last: 5
### Unpacking works with all iterables, including 
### a string into individual characters

word = "Python"
first, *middle, last = word

print(f"First: {first}")
print(f"Middle: {middle}")
print(f"Last: {last}")
First: P
Middle: ['y', 't', 'h', 'o']
Last: n

6.3.5.3. Unpacking in Function Calls#

The * operator can also unpack a list into function arguments:

# Unpack a list as function arguments
def display_info(name, age, city):
    print(f"{name} is {age} years old and lives in {city}")

person = ['Alice', 30, 'New York']
display_info(*person)  ### unpacks to display_info('Alice', 30, 'New York')
Alice is 30 years old and lives in New York
# Useful with functions like print
values = [1, 2, 3, 4, 5]
print(*values)              # Prints: 1 2 3 4 5 (separated by spaces)
print(*values, sep='-')     # Prints: 1-2-3-4-5
1 2 3 4 5
1-2-3-4-5

Common use cases:

  • Swapping values: a, b = b, a

  • Parsing CSV data: name, age, email = row.split(',')

  • Function returns: min_val, max_val = find_min_max(numbers)

  • Ignoring values: first, *_, last = data (use _ for values you don’t need)

Note:

  • _ in *_ is used as a throwaway variable name, it’s a Python convention meaning “I don’t care about this value.”