Monday, February 2nd, 2026¶

Last week, we looked at assigning and working with variables in Python. We also looked at printing and formatting strings.

Working with lists in Python¶

Another datatype in Python is the list type. Lists contain ordered collections of objects. To define a list, we surround a comma-separated collection with square brackets.

In [ ]:
 
In [ ]:
 

To access elements of a list, we use square brackets again along with an index. Python is a 0-based indexing language, which means the index of each list starts at 0. That is, 0 indicates the first item in the list.

In [ ]:
 
In [ ]:
 

We can also access elements of a list by counting backward from the end using negative indices.

  • The -1st index gives the last element.
  • The -2nd index gives the second to last element.
In [ ]:
 
In [ ]:
 

Note: We will get an error if we access indices beyond the length of the list:

In [ ]:
 
In [ ]:
 

List operations¶

What sorts of operations can we perform on lists? For arithmetic operations, lists work very similarly to strings.

Addition of lists:

In [ ]:
 

Multiplying a list and an integer:

In [ ]:
 

Lists and strings share many properties. We can convert a string to a list using the list function:

In [ ]:
 

We can find the length of a list (or string) using the len function.

In [ ]:
 
In [ ]:
 

What if we want to convert a list of string characters to a string? The str function can be used to convert objects to strings.

In [ ]:
 

Can we freely convert the string '12345' to a list and then back to a string?

In [ ]:
 

It does not look like this is doing quite what we want, since the resulting includes the list delimitors (brackets) and element separators (commas).

We can fix this by using the .join method on a string. The .join method takes in a list of strings and concetanates them. However, it uses the object from which it is called to separate each concatenation.

For example, calling 'abc'.join(['hello','goodbye','zzz']) will produce a string that concatenates the strings 'hello', 'goodbye', and 'zzz' separated by the string 'abc'. That is, it produces the string 'helloabcgoodbyeabczzz'.

In particular, if we call the .join method from an empty string '', we will get simple concatenation.

In [ ]:
 

Exercise: Use the .join method and string formatting to take in an integer n and it's prime factorization (as a list of integers) fact and print out a sentence stating the prime factorization.

In [ ]:
 
In [ ]:
 

Working with loops in Python¶

It often happens that we want to perform the same (or similar) operations many times. We can perform iterative operations using a for loop. For example, we can iterate through the items in a list and perform some desired operations.

The syntax for writing a for loop is: for (some variable name) in (some iterable object): (do something)

The variable (some variable name) will sequentially take on each of the values stored in (some iterable object) (a list, for example), and for each value will (do something).

In [ ]:
 

Key info: The spacing in Python is critical!!!. In particular, the spacing decides what operations are part of a for loop and what operations are not.

In [ ]:
 
In [ ]:
 

We can also use for loops inside other for loops. We call these "nested loops".

Exercise: Write nested for loops that iterate through all combinations of integers from the two lists [1,2,3] and [4,5,6] and print out the sum for each combination.

In [ ]:
 

What if we wanted to iterate through pairs from each list? That is, suppose we want to consider the lists in parallel and iterate through the three pairs (1,4), (2,5), and (3,6).

Exercise: Write a for loop that iterates through the two lists [1,2,3] and [4,5,6] in parallel and prints out the sum of each corresponding pair.

In [ ]:
 

Later on, we'll see how to use the zip function to achieve this goal in a more natual (and extendable) way.

The range function¶

We can use other types of iterables to setup for loops. In the examples above, we've been iterating through a pre-defined list. Suppose we want to perform some operation on the first 10,000 positive integers.

In [ ]:
 

Of course, it's not reasonable for us to write down a list of the first 10,000 positive integers in order to iterate through them. Instead, we can use the range function.

Note: We can use the help function to learn more about something in Python. For example, help(range) will tell us about the range function.

In [ ]:
help(range)

In particular:

  • range(n) will give a sequence of integers starting at 0 and going up to n-1.
  • range(m,n) will give a sequence of integers starting at m and going up to n-1.
  • range(m,n,k) will give a sequence of integers starting m, stepping by k, and stopping before n.
In [ ]:
 
In [ ]:
 
In [ ]:
 

Note: the range doesn't exactly generate a list. Instead, it is what's called a generator.

Exercise: Write Python code to print the cubes of the first $50$ positive integers.

In [ ]:
 

Constructing lists¶

So far, we've explicitly generated lists using square brackets and comma-separated inputs (which we've had to manually type in). Suppose we want to generate a list containing the cubes of the first 50 positive integers. Our current strategy is not reasonable for this sort of task.

The .append method (attached to a list) can be used to add an element to a list. That is, we can write something like <some list>.append(<some new element>) to add <some new element> to <some list>.

In [ ]:
 
In [ ]:
 

To build a list of the cubes of the first 50 positive integers, we can start with an empty list [] and then iteratively use the .append method to add elements to that list.

In [ ]:
 

Exercise: Generate a list of the squares of the first $40$ positive integers. Then print the remainder of each after division by $7$.

In [ ]:
 

Boolean expressions¶

There are two Boolean values, namely True and False.

We can write statements that evalute to either True or False called Boolean expressions. For example, we can compare two numbers using < or > to see if one is less than the other or one is greater than the other.

In [ ]:
 
In [ ]:
 
In [ ]:
 

Similarly, we can use <= or >= for less than/greater than or equal to.

In [ ]:
 
In [ ]:
 
In [ ]:
 

Inequality checks can also be chained together.

In [ ]:
 
In [ ]:
 

We can use a double equality == to check whether two objects are equal to one another.

In [ ]:
 
In [ ]:
 

We can also check whether two lists are equal to one another (i.e. if they contain equal objects in the same order).

In [ ]:
 
In [ ]:
 

We can construct more complicated Boolean expressions using the and, or, and not operators. That is:

  • (some expression) and (some other expression) will evaluate as True if (some expression) and (some other expression) are both True.
  • (some expression) or (some other expression) will evaluate as True if either (some expression) or (some other expression) are True (or both).
  • not (some expression) will evaluate as True if (some expression) is False.
In [ ]:
 
In [ ]:
 
In [ ]:
 

Using if statements¶

We can use an if statement to perform some operations only when a Boolean expression is True. The syntax for writing an if statement is: if (some Boolean expression): (do something)

Again, spacing is CRITICAL, as it indicates which operations are part of the if statement (which will only run when the Boolean expression is True), and which operations are outside of the if statement (which will run regardless).

In [ ]:
 
In [ ]:
 

Optionally, we can include an else block immediately following an if block. In this case, the code inside the else block will only occur if the Boolean expression in the if statement was False.

In [ ]:
 

Exercise: Use an if/else pair to print a string stating whether an integer n is even or odd.

In [ ]:
 

We very often want to perform different operations based on several Boolean expressions. We can supplement an if statement with an elif statement (which is short for "else if") with a new Boolean expression to perform operations only in the case that the first if expression was False and the new expression is True.

In [ ]:
 

We can include many elif blocks to check different cases.

In [ ]:
 

Exercise: Use an if/elif/else triple to print a string stating whether an integer n is a multiple of $3$, one more than a multiple of $3$, or two more than a multiple of $3$.

In [ ]:
 

Exercise: Out of the squares of the first 40 positive integers, count how many have remainder $1$ of each after division by $7$.

In [ ]:
 
In [ ]:
 

Some thoughts about efficiency:

Prime numbers¶

Our first project will deal with prime numbers. It will be useful if we can develop some code to decide whether a given integer is prime or not. One strategy for checking whether a given number is prime or not is to look for numbers that evenly divide it. That is, we can test a number $n$ for primality by looking for numbers $d$ such that the remainder from dividing $n$ by $d$ is zero.

In [ ]:
 

Exercise: Write code that will set a Boolean variable to True if an integer n is prime and will set the Boolean variable to False if not.

In [ ]:
 
In [ ]:
 

The break and continue commands¶

The break command can be used within a loop to immediately exit the loop.

In [ ]:
 

Exercise: Modify the prime-checking code above to exit the loop as soon as n is determined to not be prime.

In [ ]:
 

Other times, we may want to immediately proceed to the next iteration of a loop. The continue command can be used to accomplish this.

In [ ]: