Twists in the List Genome

Jed Rembold

October 17, 2025

Announcements

  • Project 2: Breakout due on Monday! Getting collisions figured out by the end of today would be a great target!
  • Grade reports went out!!
  • Make sure you look at your Wordle feedback to apply to Breakout!
  • I have meetings for most of the afternoon, but will be around between 4:30 and 6:30 if you have Breakout questions before the weekend
  • Polling: polling.jedrembold.prof

Sequences

  • Lists are a bit like more flexible strings in many ways!
  • Strings and lists are examples of a more general class of object in Python called a sequence
  • Many of the basic string operations are actually sequence operations, and thus also apply to lists!
  • The len function
  • Index numbering starting at 0
  • Concatenation using + or +=
  • Selection of an individual element using square brackets
  • Looping over elements
  • Negative index numbering counting backwards from the end
  • Slicing in all forms
  • Comparing sequences
  • Repetition using *
  • Inclusion testing using in operator

Understanding Check!

What would the below expression evaluate to?

['One', 2, True][-1:1:-1][0]
  1. ['One']
  2. 2
  3. True
  4. None of the above, or this will error

X-Lists

Mutants

  • The most important difference between strings and lists is one of mutability
    • Strings we have already identified as being immutable: you can not change the individual elements
    • Lists, in contrast, are mutable, which means that we can change or assign new values to the elements of a list
  • Immutable objects have many advantages in programming:
    • You don’t have to worry about if the values will change
    • Immutable values can be more easily shared
    • Immutable objects are easier to use with concurrent programs
  • In some situations though, mutable objects are the perfect tool for the job

Locations in Memory

  • Thinking about mutable objects requires a shift in how we visualize our code interacting with the objects in memory
  • We can “see” the location in memory where Python is storing an object with the id(|||object|||) function
>>> A = 5
>>> id(A)
129257497672776
>>> B = 5
>>> id(B)
129257497672776
>>> C = [5]
>>> id(C)
129257425943936
>>> D = [5]
>>> id(D)
129257426156544

For Reference

  • When working with mutable objects, it is better to think of the variable as holding a reference to the object, rather than the actual contents of the object
  • I find it useful to think of a reference as the “address” in memory where that object’s contents can be found
    • The treasure map showing where you can find the object!
  • This undeniably complicates things, as referencing a mutable object lets you change it, which will immediately be reflected in anything else that referenced that object!
  • Mutable objects can be terrific to work with, as their mutability makes them very flexible, but be wary of unexpected behavior

Following along Mutable Lists

  • Let’s walk through an example of the code to the right
    • == compares the contents of lists
    • is compares the ids of lists
cool = ['blue', 'violet']
warm = ['red', 'orange']

colors = [cool, warm]
other_colors = [['blue', 'violet'],
                ['red', 'orange']]

print(colors == other_colors)
print(colors is other_colors)

cool[0] = 'indigo'
warm = ['orange', 'yellow']

print(colors)
print(other_colors)

Lists as Arguments

  • When you pass a list as an argument to a function or return a list as a result, only the reference to the list is actually passed back and forth
  • This means that the elements of the list are effectively shared between the function and the caller
    • Changes that the function makes to the elements will persist after the function returns
  • Example of reversing a list in PythonTutor: here

Sneaky Mutability

  • List’s mutability can frequently be very nice to work with, but as with lists as arguments to functions, you need to be careful in some instances to ensure you understand how Python is treating the list
  • I’ve encountered a few other problems where it can be easy to mess up:
    • Initializing a list to look like another list, wanting to make changes and then compare it to the original
    • Looping over a mutating list

Cloning

  • What can we do in these sorts of instances to not let mutability trip us up?
  • Clone the list instead of just assigning a reference
    • Creates a new object in memory
  • Several ways you can make a shallow clone (in code)
    • Using the .copy() list method
    • Any slice always returns a new object
    • Using the list() function will return a new object

List Methods

Common Useful List Methods

Method Description
|||list|||.copy() Returns a new list whose elements are the same as the original
|||list|||.append(|||value|||) Adds |||value||| to the end of the list
|||list|||.insert(|||idx|||, |||val|||) Inserts |||val||| before the specified |||idx|||
|||list|||.remove(|||value|||) Removes the first instance of |||value||| from the list, or errors
|||list|||.reverse() Reverses the order of the elements in the list
|||list|||.sort() Sorts the elements of the list. Can take an optional argument |||key||| to specify how to sort

Functions on Iterators

  • The .sort and .reverse methods reorder the list in place and do not return anything
  • Commonly, you might want to loop through a list in a particular order, but not change the original list
  • Python gives you two matching functions to do this, which return a new ordered version of the list, without changing the original
    • The reversed() function creates a new iterable object that returns its elements in the opposite order
    • The sorted() function creates a new iterable object that returns its elements in ascending order

Understanding Check

Given the code to the right, what would be the printed value of A?

  1. ['Fox', 'Giraffe', 'Hippo', 'Iguana']
  2. ['Fox', 'Hippo', 'Iguana']
  3. ['Iguana', 'Fox']
  4. ['Fox', 'Iguana']
A = [
     'Fox',
     'Giraffe', 
     'Hippo'
    ]
A.append('Iguana')
A[:].reverse()
B = A
for anim in B:
    if anim[1] == 'i':
        B.remove(anim)
print(A)

List Comprehension

List building with loops

  • Commonly will make lists with a simple:

    even_digits = [ 2, 4, 6, 8 ]
  • But in many cases, it is easier to specify the elements of a list using a sequence of values generated by a for loop. For instance

    even_digits = [ ]
    for i in range(0, 10, 2):
        even_digits.append(i)
  • Python gives us a shorthand notation to achieve this:

    even_digits = [ i for i in range(0, 10, 2) ]
    • Called list comprehension

Comprehending Lists

  • The simplest list comprehension syntax is:

    [ |||expression||| |||iterator||| ]

    where |||expression||| is any Python expression and |||iterator||| is a for loop header

  • The iterator component can be followed by any number of additional modifiers

    • More for loop headers for nested loops
    • or if statements to select specific values
  • Example: all even numbers to 20 not also visible by 3

    [i for i in range(0,2,20) if i % 3 != 0]

Forever Friends: Strings and Lists

Where Strings and Lists Meet

  • There are a handful of methods that transition between strings and lists
Method Description
str.split() Splits a string into a list of its components using whitespace as a separator
str.split(sep) Sprits a string into a list using the specified separator sep
str.splitlines() Splits a string into of list of strings at the newline character
str.join(list) Joins the elements of the list into a string, using str as the separator

Tabulation

  • Arrays can also be useful when you have a set of values and you need to count how many values fall into a different ranges
    • Process is called tabulation
  • The idea is that for each piece of data we encounter, we figure out a corresponding index in our tabular array and then increment the value of that element
  • Your book shows this for seeing how many times each letter of the alphabet appears in a text sequence
  • Let’s instead look at an example of determining how many students got different letters grades on a made-up final
// reveal.js plugins