Class Notes: 1d Lists

  1. The Basics
    1. Creating Lists [Pre-reading]
    2. Built-in Functions with Lists [Pre-reading]
    3. Comparing Lists [Pre-reading]
    4. Accessing Elements (Indexing and Slicing) [Pre-reading]
    5. Modifying Lists [Pre-reading]

  2. Lists are Mutable
    1. List Mutability and Aliasing [Pre-reading]
    2. Copying Lists [Pre-reading]
    3. Destructive and Non-destructive Functions

  3. Coding with Lists
    1. Finding Elements
    2. Adding Elements
    3. Removing Elements
    4. Looping Over Lists
    5. List Methods: Sorting and Reversing
    6. Summary: Destructive and Non-destructive

  4. Additional Information
    1. Tuples (Immutable Lists)
    2. List Comprehensions
    3. Converting Between Lists and Strings
    4. Worked Examples Using Lists

  1. Creating Lists [Pre-reading]
  2. Built-in Functions with Lists [Pre-reading]
  3. a = [2, 3, 5, 2] print("a = ", a) print("len =", len(a)) print("min =", min(a)) print("max =", max(a)) print("sum =", sum(a))

  4. Comparing Lists [Pre-reading]

  5. To help us understand how to compare lists, let's first discuss a few things about Python objects. We've actually seen quite a few examples of objects in Python, including ints, floats, strings, etc. In fact, everything in Python is an object.

    Python objects always have three pieces:
    You can think of the object id as kind of a serial number for each object. This id will help us to determine if two variable names represent the exact same list or not. See the difference between == and is below.

    # Create some lists a = [10, 20, 30] b = a c = [10, 20, 30] # Is c the same as a and b?? d = [10, 20, 33] # d is totally different print("a:", a) print("b:", b) print("c:", c) print("d:", d) print() # Variable names a and b both point to the exact same list object # We can confirm this by printing the id for each variable name print("id(a):", id(a)) print("id(b):", id(b)) print("id(c):", id(c)) print("id(d):", id(d)) print() # c is a list that has the same contents as a (and b) but is actually a # different object # Use the visualize button to help see this difference in pythontutor # Operator list1 == list2 checks to see if the two objects are # "equal", specifically: # 1) both objects are lists # 2) both lists have the same length # 3) the corresponding elements in each list are equal # Operator list1 is list2 checks to see if the two objects are # actually the same object, specifically: both objects have the same id print("a == b:", (a == b)) print("a == c:", (a == c)) print("a == d:", (a == d)) print() print("a is b:", (a is b)) print("a is c:", (a is c)) print("a is d:", (a is d)) print() print("a != b:", (a != b)) print("a != c:", (a != c)) print("a != d:", (a != d)) print() print("a is not b:", (a is not b)) print("a is not c:", (a is not c)) print("a is not d:", (a is not d))

  6. Accessing Elements (Indexing and Slicing) [Pre-reading]
  7. # Indexing and slicing for lists works the same way as it did for strings! a = [2, 3, 5, 7, 11, 13] print("a =", a) # Access non-negative indexes print("a[0] =", a[0]) print("a[2] =", a[2]) # Access negative indexes print("a[-1] =", a[-1]) print("a[-3] =", a[-3]) # Access slices a[start:end:step] print("a[0:2] =", a[0:2]) print("a[1:4] =", a[1:4]) print("a[1:6:2] =", a[1:6:2])

  8. Modifying Lists [Pre-reading]
  9. dna = ['G', 'A', 'T', 'T', 'A', 'C', 'A'] print(id(dna)) print(dna) dna[0] = 'C' print(dna) dna[3] = 'G' print(dna) dna[-2] = 'G' print(dna) print(id(dna)) # Note the object id stayed the same. We "mutated" the list object rather than # making new list objects

    Other ways to modify (mutate) a list
    a = [10, 20, 30, 20] print(id(a)) print(a) a.append(10) # Add element to the end print(a) a.insert(2, 25) # Insert 25 into index 2 (bumping others to the right) print(a) a.pop() # Remove element from the end print(a) a.pop(3) # Remove element at index 3 print(a) a.remove(20) # Remove (first occurrence of) element with value 20 print(a) print(id(a)) # Same id as before we did any of these mutations # Append, insert, pop and remove are all examples of "destructive" methods, i.e. # methods that change the contents of the list *without* creating a new list

  10. List Mutability and Aliasing [Pre-reading]

  11. Unlike strings, lists are mutable. This means that they can be changed, without creating a new list.
    This also forces us to better understand aliases, when two variables reference the same value. Aliases are only interesting (and challenging) for mutable values like lists.
    Note: it will be especially helpful to use the Visualize feature in the following examples.

  12. Copying Lists [Pre-reading]
  13. Destructive and Non-destructive Functions

  14. Because lists are mutable, we can change them in two ways:
    destructively (which modifies the original value directly), and
    non-destructively (which creates a new list and does not modify the original value).
    This also affects how we write functions that use lists.

  15. Finding Elements
  16. Adding Elements

  17. Removing Elements
  18. Looping Over Lists
  19. List Methods: Sorting and Reversing

  20. Lists have many built-in methods. It's common for these methods to be implemented both destructively and non-destructively.

  21. Summary: Destructive and Non-destructive
  22. Some destructive vs. non-destructive list analogs, for:

    a = ['cat','dog','pig','cow']

    Destructive (aliasing) Nondestructive
    b = a
    b = copy.copy(a)
    b = a[:]
    b = a + []
    b = list(a)
    a.append('axolotl') # just the elem
    a.extend(['axolotl']) # watch the brackets
    a += ['axolotl'] # also needs brackets
    a = a + ['axolotl']
    x = a.pop() # equivalent to x = a.pop(-1)
    x = a[-1] # Get the last element a = a[:-1] # Then make the smaller copy
    x = a.pop(2) # index
    x = a[2] a = a[:2] + a[3:]
    i = a.index('pig') a = a[:i] + a[i+1:]
    a.insert(2, 'axolotl') # index, element
    a = a[:2] + ['axolotl'] + a[2:]
    a = sorted(a)
    a = list(reversed(a))
    (Need to wrap with list() because the reversed function evaluates to something called an iterator.)


  23. Tuples (Immutable Lists)

  24. Tuples are exactly like lists, except they are immutable. We cannot change the values of a tuple.

  25. List Comprehensions

  26. List comprehensions are a handy way to create lists using simple loops all in one line.
    # Long way a = [] for i in range(10): a.append(i) print(a) # Short way a = [i for i in range(10)] print(a) # We can also add conditionals at the end (but keep it simple!) a = [(i*100) for i in range(20) if i%5 == 0] print(a)

  27. Converting Between Lists and Strings
  28. # use list(s) to convert a string to a list of characters a = list("wahoo!") print(a) # prints: ['w', 'a', 'h', 'o', 'o', '!'] # use s1.split(s2) to convert a string to a list of strings delimited by s2 a = "How are you doing today?".split(" ") print(a) # prints ['How', 'are', 'you', 'doing', 'today?'] # use "".join(a) to convert a list of characters to a single string print("".join(a)) # prints: Howareyoudoingtoday? # "".join(a) also works on a list of strings (not just single characters) a = ["parsley", "is", "gharsley"] # by Ogden Nash! print("".join(a)) # prints: parsleyisgharsley print(" ".join(a)) # prints: parsley is gharsley

  29. Worked Examples Using Lists
  30. If you want to review more examples of problem-solving with lists, you can find several worked examples here. We'll go over some of these in class as well.