Programming 1, 2021-2
Lecture 4: Notes

Some of today's topics are covered in these sections of Think Python:

Here are some additional notes.

String formatting

Python includes f-strings, which are formatted strings that can contain interpolated values. For example:

color1 = 'blue'
color2 = 'green'

print(f'The sky is {color1} and the field is {color2}')

Write the character f immediately before a string to indicate that it is a formatted string. Interpolated values can be arbitrary expressions:

x = 14
y = 22

print(f'The sum is {x + y}.')

You may optionally specify a format code after each interpolated value to indicate how it should be rendered as a string. Some common format codes include

For example:

m = 127
e = 2.718281828459045

print(f'm in hex is {m:x}')   # prints 'm in hex is 7f'
print(f'e is {e:.4f}')        # prints 'e is 2.7183'

You can specify a comma (',') before a 'd' or 'x' formatt code to specify that digits should be printed in groups of 3, with a separator between groups:

>>> x = 2 ** 100
>>> f'{x:,d}'
'1,267,650,600,228,229,401,496,703,205,376'

An integer preceding a format code indicates a field width. If the value's width in characters is less than the field width, it will be padded with spaces on the left:

>>> f'{23:9d}'
'       23'
>>> f'{723:9d}'
'      723'
>>> f'{72377645:9d}'
' 72377645'

If the field width is preceded with a '0', then the output will be padded with zeroes instead:

>>> f'{23:09d}'
'000000023'
>>> f'{723:09d}'
'000000723'
>>> f'{72377645:09d}'
'072377645'

There are many more format codes that can you can use to control output formatting in more detail. See the Python library documentation for a complete description of these.

lists

Lists are a fundamental type in Python. We can make a list by specifying a series of values surrounded by square brackets:

l = [3, 5, 9, 11, 15]

A list may contain values of various types:

l = ['horse', 789, False, -22.3]

It may contain any number of values, or may even be empty:

l = []

The len function returns the number of elements in a list:

len(['potato', 'tomato', 'tornado'])    # returns 3

We can access elements of a list by index. The first element has index 0, and the last element has index len(l) – 1:

>>> l = [3, 5, 9, 11, 15]
>>> l[0]
3
>>> l[4]
15

Just like with strings, we can use negative indices to count from the end of the list:

>>> l = [3, 5, 9, 11, 15]
>>> l[-1]
15
>>> l[-2]
11

Slice syntax works with lists, just like with strings:

>>> l = [3, 5, 9, 11, 15]
>>> l[1:3]
[5, 9]
>>> l[3:]
[11, 15]

The 'in' operator tests whether a list contains a given value:

>>> 77 in [2, 8, 77, 3, 1]
True

Unlike strings, lists in Python are mutable. We can set values by index:

>>> l = [3, 5, 9, 11, 15]
>>> l[0] = 77
>>> l[3] = 99
>>> l
[77, 5, 9, 99, 15]

A list's length may change over time. The append() method adds a single element to a list, and the extend() method adds a series of elements. The += operator is a synonym for extend():

>>> l = [3, 5, 9, 11, 15]
>>> l.append(20)
>>> l.append(30)
>>> l
[3, 5, 9, 11, 15, 20, 30]
>>> l += [100, 200, 30]
>>> l
[3, 5, 9, 11, 15, 20, 30, 100, 200, 30]

The insert() method inserts an element into a list at a given position:

>>> l = [3, 5, 9, 11, 15]
>>> l.insert(2, 88)
>>> l
[3, 5, 88, 9, 11, 15]

The del operator can delete one or more elements of a list by index:

>>> l = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'grape']
>>> del l[1]
>>> l
['orange', 'pear', 'banana', 'kiwi', 'grape']
>>> del l[2:4]
>>> l
['orange', 'pear', 'grape']

Note that lists, ranges, and strings are all considered to be sequences in Python. The 'for' statement can loop over any sequence, and certain operations such as len() and slices also work on any sequence.

The list() function converts any sequence to a list. Note its effect on a string or a range:

>>> list('watermelon')
['w', 'a', 't', 'e', 'r', 'm', 'e', 'l', 'o', 'n']
>>> list(range(120, 130))
[120, 121, 122, 123, 124, 125, 126, 127, 128, 129]

See our quick reference guide to read about additional useful list methods.

structural and reference equality

Suppose that we write the following declarations:

>>> l = [3, 5, 7, 9]
>>> m = l

Now the variables l and m refer to the same list. If we change l[0], then the change will be visible in m:

>>> l[0] = 33
>>> m[0]
33

Alternatively, we may make a copy of the list l. There are several possible ways to do that:

>>> l = [3, 5, 7, 9]
>>> n = l.copy()      # technique 1: call the copy() method
>>> n = list(l)       # technique 2: call the list() function
>>> n = l[:]          # technique 3: use slice syntax

Now the list n has the same values as l, but it is a different list. Changes in one list will not be visible in the other:

>>> l[1] = 575
>>> l
[3, 575, 7, 9]
>>> n
[3, 5, 7, 9]

Python provides two different operators for testing equality. The first is the == operator:

>>> x == y
True
>>> x == z
True

This operator tests for structural equality. In other words, given two lists, it compares them element by element to see if they are equal. (It will even descend into sublists to compare elements there as well.)

The second equality operator is the is operator:

>>> x is y
True
>>> x is z
False

This operator tests for reference equality. In other words, it returns true only if its arguments actually refer to the same object.

You may want to use each of these operators in various situations. Note that is returns instantly, whereas == may traverse a list in its entirety, so it runs in O(N) in the worst case.