Lecture 6 – Control

Data 94, Spring 2021

Motivating Example

In [1]:
def ready_to_graduate(year, units):
    return (year == 'senior') and (units >= 120)
In [2]:
ready_to_graduate('junior', 121)
Out[2]:
False
In [3]:
ready_to_graduate('senior', 121)
Out[3]:
True
In [4]:
def ready_greeting(year, units):
    is_ready = ready_to_graduate(year, units)
    if is_ready:
        print('ready to graduate!')
    else:
        print('not ready yet.')
In [5]:
ready_greeting('junior', 121)
not ready yet.
In [6]:
ready_greeting('senior', 121)
ready to graduate!

If-statements

The most basic if-statements only include an if.

In [7]:
def fancy_print(n):
    if n == 23:
        print('I love this number!')
    print(n)
In [8]:
fancy_print(5)
5
In [9]:
fancy_print(23)
I love this number!
23
In [10]:
def fancier_print(n):
    if n == 23:
        print('I love this number!')
    else:
        print('This is not my favorite number.')
    print(n)
In [11]:
fancier_print(5)
This is not my favorite number.
5
In [12]:
fancier_print(23)
I love this number!
23

You don't always need to use else.

In [13]:
def safe_divide(a, b):
    if b == 0:
        return 0
    return a / b
In [14]:
safe_divide(5, 0)
Out[14]:
0
In [15]:
safe_divide(5, 2)
Out[15]:
2.5

The above is equivalent to this; I personally prefer the above.

def safe_divide(a, b):
    if b == 0:
        return 0
    else:
        return a / b

Quick Check 1

In [16]:
def a_max(a, b, c):
    ...
In [ ]:
 

Be concise!

In [17]:
def is_23(n):
    if n == 23:
        return True
    else:
        return False
    
def is_23(n):
    return n == 23

Elif

Let's build a grades calculator, according to this table:

Letter Range
A [90, 100]
B [80, 90)
C [70, 80)
D [60, 70)
F [0, 60)

Note, $[a, b)$ refers to the set of numbers that are greater than or equal to $a$, but less than $b$.

In [18]:
# if grade is between 90 and 100: return 'A'
# if grade is between 80 and 90: return 'B'
# if grade is between 70 and 80: return 'C'
# ...
In [19]:
# Takes in grade as number, computes letter grade, and prints 'Grade: letter'
def grade_converter(grade):
    if grade >= 90:
        return 'A'
    elif grade >= 80:
        return 'B'
    elif grade >= 70:
        return 'C'
    elif grade >= 70:
        return 'D'
    else:
        return 'F'
In [20]:
grade_converter(89)
Out[20]:
'B'
In [21]:
grade_converter(70)
Out[21]:
'C'

Here it's worth illustrating the difference between using elif and many ifs.

In [22]:
def grade_converter_print(grade):
    if grade >= 90:
        print('A')
    if grade >= 80:
        print('B')
    if grade >= 70:
        print('C')
    if grade >= 70:
        print('D')
    else:
        print('F')
In [23]:
grade_converter_print(89)
B
C
D
In [24]:
grade_converter_print(70)
C
D

The fact that we're using return and elif changes the behavior of our code dramatically. Watch out for this!

Quick Check 2

In [25]:
def num_pos(a, b):
    ...
In [ ]:
 
In [ ]:
 

Indentation

In [26]:
def indent_example(x):
    if x > 5:
        print('somewhat big!')
        if x % 2 == 0:
            print('and even too!')
    else:
        print('tiny.')
In [27]:
indent_example(15)
somewhat big!
In [28]:
indent_example(14)
somewhat big!
and even too!
In [29]:
indent_example(4)
tiny.

Truthy Values

In [30]:
bool(15)        # True
Out[30]:
True
In [31]:
bool(None)      # False
Out[31]:
False
In [32]:
def weird(x):
    if x:
        print('x is not 0')
    else:
        print('x is 0')
In [33]:
weird(5)
x is not 0
In [34]:
weird(0)
x is 0
In [35]:
def is_empty(s):
    return not s
In [36]:
is_empty('')
Out[36]:
True
In [37]:
is_empty('zebra')
Out[37]:
False

Demo

You should ignore all of the following code, except for the cell containing the definition of the function state_color.

In [38]:
import folium
from datascience import *

data = Table.read_table('data/states_elections.csv')
state_capitals = Table.read_table('data/us-state-capitals.csv')
data = data.join('State', state_capitals, 'name').select(['State', 'description', 'latitude', 'longitude', '2020']) \
    .relabeled(['State', 'description', '2020'], ['state', 'capital', 'federal vote'])
In [39]:
data
Out[39]:
state capital latitude longitude federal vote
Alabama Montgomery 32.3777 -86.3006 R
Alaska Juneau 58.3016 -134.42 R
Arizona Phoenix 33.4481 -112.097 D
Arkansas Little Rock 34.7466 -92.289 R
California Sacramento 38.5767 -121.494 D
Colorado Denver 39.7392 -104.985 D
Connecticut Hartford
41.764 -72.6822 D
Delaware Dover 39.1573 -75.5197 D
Florida Tallahassee 30.4381 -84.2813 R
Georgia Atlanta
33.749 -84.3882 D

... (40 rows omitted)

In [40]:
def make_label(r):
    return r[1] + ', ' + r[0]

data = data.with_columns('labels', data.apply(make_label))
In [41]:
Marker.map_table(data.select('latitude', 'longitude', 'labels'))
Out[41]:
Make this Notebook Trusted to load map: File -> Trust Notebook

Now, don't ignore this cell!

In [42]:
def state_color(state, vote):
    if state == 'California':
        return 'green'
    elif vote == 'D':
        return 'blue'
    else:
        return 'red'
In [43]:
data = data.with_columns('colors', ['']*data.num_rows)
data = data.with_columns('colors', data.apply(lambda r: state_color(r[0], r[-3])))

Marker.map_table(data.select('latitude', 'longitude', 'labels', 'colors'))
Out[43]:
Make this Notebook Trusted to load map: File -> Trust Notebook