Control

Tips for navigating the slides:
  • Press O or Escape for overview mode.
  • Press the copy icon on the upper right of code blocks to copy the code

Class outline:

  • Side effects
  • More function features
  • Conditionals
  • Booleans
  • Iteration

Side effects

The None value

The special value None represents nothingness in Python.

Any function that doesn't explicitly return a value will return None:


            def square_it(x):
                x * x
            

When a function returns None, the console shows no output at all:


            square_it(4)
            

Attempting to treat the None like a number will result in an error:


            sixteen = square_it(4)
            sum = sixteen + 4     # 🚫 TypeError!
            

Side effects

A side effect is when something happens as a result of calling a function besides just returning a value.

The most common side effect is logging to the console, via the built-in print() function.


            print(-2)
            

A similar side effect is writing to a file:


            f = open('songs.txt', 'w')
            f.write("Dancing On My Own, Robyn")
            f.close()
            

Side effects vs. Return values


            def square_num1(number):
                return pow(number, 2)
            

            def square_num2(number):
                print(number ** 2)
            
  • Which one has a side effect?
    The second function has a side effect, because it prints to the console.

  • What data type do they each return?
    The first function returns a number, the second one returns None.

Pure vs. non-pure functions

Arguments Return value
Pure functions
just return values.
-2 abs() function 2
2, 10 pow() function 1024
Non-pure functions
have side effects.
-2 print() function
Python displays output "-2"
None

Nested print statements

What will this display?


            print(print(1), print(2))
            
print(print(1), print(2)) def print()... print(1) def print()... 1 Display "1" None print(2) def print()... 2 Display "2" None Display "None None" None

More function features

Default arguments

In the function signature, a parameter can specify a default value. If that argument isn't passed in, the default value is used instead.


            def calculate_dog_age(human_years, multiplier = 7):
                return human_years * multiplier
            

These two lines of code have the same result:


            calculate_dog_age(3)
            calculate_dog_age(3, 7)
            

Default arguments can be overriden two ways:


            calculate_dog_age(3, 6)
            calculate_dog_age(3, multiplier=6)
            

Multiple return values

A function can specify multiple return values, separated by commas.


            def divide_exact(n, d):
                quotient = n // d
                remainder = n % d
                return quotient, remainder
            

Any code that calls that function must also "unpack it" using commas:


            q, r = divide_exact(618, 10)
            

Doctests

Doctests check the input/output of functions.


            def divide_exact(n, d):
                """
                >>> q, r = divide_exact(2021, 10)
                >>> q
                202
                >>> r
                1
                """
                quotient = n // d
                remainder = n % d
                return quotient, remainder
            

See more in Python doctests documentation.

Boolean expressions

Booleans

A Boolean value is either True or False and is used frequently in computer programs.

Google Maps uses a boolean to decide whether to avoid highways in driving directions:


            avoid_highways = True
            

Twitter uses a boolean to remember where the user allows personalized ads:


            personalized_ads = False
            

Boolean expressions

An expression can evaluate to a Boolean. Most Boolean expressions use either comparison or logical operators.


An expression with a comparison operator:


            passed_class = grade > 65
            

An expression with a logical operator:


            wear_jacket = is_raining or is_windy
            

Comparison operators

Operator Meaning True expressions
== Equality 32 == 32
!= Inequality 30 != 32
> Greater than 60 > 32
>= Greater than or equal 60 >= 32, 32 >= 32
< Less than 20 < 32
<= Less than or equal 20 <= 32, 32 <= 32

⚠️ Common mistake: Do not confuse = (the assignment operator) with == (the equality operator).

Logical operators

Operator True expressions Meaning
and 4 > 0 and -2 < 0 Evaluates to True if both conditions are true. If one is False evaluates to False.
or 4 > 0 or -2 > 0 Evaluates to True if either condition is true. Evaluates to False only if both are false.
not not (5 == 0) Evaluates to True if condition is false; evaluates to False if condition is true.

Compound booleans

When combining multiple operators in a single expression, use parentheses to group:


            may_have_mobility_issues = (age >= 0 and age < 2)  or age > 90
            

Boolean expressions in functions

A function can use a Boolean expression to return a result based on the values of the parameters.


            def passed_class(grade):
                return grade > 65
            

            def should_wear_jacket(is_rainy, is_windy):
                return is_rainy or is_windy
            

Exercise

These are un-graded exercises you can do after the lecture to make sure you grok the basics:

Statements

Statements

A statement is executed by the interpreter to perform an action.

So far we've seen a few...

Statement type Example
Assignment statement

                        name = 'sosuke'
                        greeting = 'ahoy, ' + name
                        
Def statement

                        def greet(name):
                            return 'ahoy, ' + name
                        
Return statement

                        return 'ahoy, ' + name
                        

Compound statements

A compound statement contains groups of other statements.


            
<header>: # CLAUSE
<statement> # SUITE <statement> ...
<separating header>: # CLAUSE
<statement> # SUITE <statement> ...

The first header determines a statement's type, and the header of each clause controls the suite that follows.

Execution of suites

A suite is a sequence of statements.


            <header>:
            
<statement> # SUITE <statement> ...
<separating header>:
<statement> # SUITE <statement> ...

Execution rule for a sequence of statements:

  • Execute the first statement
  • Unless directed otherwise, execute the rest

Conditional statements

Conditional statements

A conditional statement gives your code a way to execute a different suite of code statements based on whether certain conditions are true or false.


            if <condition>:
                <statement>
                <statement>
                ...
            

A simple conditional:


            clothing = "shirt"

            if temperature < 32:
                clothing = "jacket"
            

Compound conditionals

A conditional can include any number of elif statements to check other conditions.


            if <condition>:
                <statement>
                ...
            elif <condition>:
                <statement>
                ...
            elif <condition>:
                <statement>
                ...
            

            clothing = "shirt"

            if temperature < 0:
                clothing = "snowsuit"
            elif temperature < 32:
                clothing = "jacket"
            

The else statement

A conditional can include an else to specify code to execute if no previous conditions are true.


            if <condition>:
                <statement>
                ...
            elif <condition>:
                <statement>
                ...
            else:
                <statement>
                ...
            

            if temperature < 0:
                clothing = "snowsuit"
            elif temperature < 32:
                clothing = "jacket"
            else:
                clothing = "shirt"
            

Conditional statements summary


            if num < 0:
                sign = "negative"
            elif num > 0:
                sign = "positive"
            else:
                sign = "neutral"
            

Syntax tips:

  • Always start with if clause.
  • Zero or more elif clauses.
  • Zero or one else clause, always at the end.

Execution of conditional statements

Each clause is considered in order.

  • Evaluate the header's expression.
  • If it's true, execute the suite of statements underneath and skip the remaining clauses.
  • Otherwise, continue to the next clause.
Screenshot of a conditional statement in PythonTutor

Conditionals in functions

It's common for a conditional to be based on the value of the parameters to a function.


            def get_number_sign(num):
                if num < 0:
                    sign = "negative"
                elif num > 0:
                    sign = "positive"
                else:
                    sign = "neutral"
                return sign
            

            get_number_sign(50)  # "positive"
            get_number_sign(-1)  # "negative"
            get_number_sign(0)   # "neutral"
            

Returns inside conditionals

A branch of a conditional can end in a return, which exits the function entirely.


            def get_number_sign(num):
                if num < 0:
                    return "negative"
                elif num > 0:
                    return "positive"
                else:
                    return "neutral"
            

            get_number_sign(50)  # "positive"
            get_number_sign(-1)  # "negative"
            get_number_sign(0)   # "neutral"
            

Exercise

These are un-graded exercises you can do after the lecture to make sure you grok the basics:

While loops

Why loops?

Consider the following code...


            print(9 * 1)
            print(9 * 2)
            print(9 * 3)
            print(9 * 4)
            print(9 * 5)
            

This code is repetitive and variable, but the variability is sequential - it just adds one to the right-hand side number each time. In English, we could describe this as "print out the first 5 multiples of 9".

We can simplify this code with a loop!

While loops

The while loop syntax:


            while <condition>:
                <statement>
                <statement>
            

As long as the condition is true, the statements below it are executed.


            multiplier = 1
            while multiplier <= 5:
                print(9 * multiplier)
                multiplier += 1
            

The code is significantly shorter, and it can easily be extended to loop for more or less iterations.

Changing a while loop #1

You can change the initial values of the variables used in the condition:


            multiplier = 3
            while multiplier <= 5:
                print(9 * multiplier)
                multiplier += 1
            
  • What will be the first thing displayed? 27
  • What will be the last thing displayed? 45
  • How many iterations? 3 (for values of 3, 4, 5)

Changing a while loop #2

You can change the condition:


            multiplier = 3
            while multiplier <= 10:
                print(9 * multiplier)
                multiplier += 1
            
  • What will be the first thing displayed? 27
  • What will be the last thing displayed? 90
  • How many iterations? 8 (for values of 3, 4, 5, 6, 7, 8, 9, 10)

Changing a while loop #3

You can change how much the values change between iterations:


            multiplier = 3
            while multiplier <= 10:
                print(9 * multiplier)
                multiplier += 2
            
  • What will be the first thing displayed? 27
  • What will be the last thing displayed? 81
  • How many iterations? 4 (for values of 3, 5, 7, 9)

Changing a while loop #4

You can change the computation inside the while loop:


            multiplier = 3
            while multiplier <= 10:
                print(10 * multiplier)
                multiplier += 2
            
  • What will be the first thing displayed? 30
  • What will be the last thing displayed? 90
  • How many iterations? 4 (for values of 3, 5, 7, 9)

Using a counter variable

It's common to use a counter variable whose job is keeping track of the number of iterations.


            total = 0
            counter = 0
            while counter < 5:
                total += pow(2, 1)
                counter += 1
            

The counter variable may also be involved in the loop computation:


            total = 0
            counter = 0
            while counter < 5:
                total += pow(2, counter)
                counter += 1
            

Beware infinite loops

Uh oh..


            counter = 1
            while counter < 5:
                total += pow(2, counter)
            

What one line of code would fix this?
counter += 1


            counter = 6
            while counter > 5:
                total += pow(2, counter)
                counter += 1
            

How do we save this code?
Intentions are unclear! Change the initial value and condition?

Execution of loops

  1. Evaluate the header’s Boolean expression.
  2. If it is a true value, execute the suite of statements, then return to step 1.
Screenshot of a loop in PythonTutor

Loops in functions

A loop in a function will commonly use a parameter to determine some aspect of its repetition.


            def sum_up_squares(start, end):
                counter = start
                total = 0
                while counter <= end:
                    total += pow(counter, 2)
                    counter += 1
                return total

            sum_up_squares(1, 5)
            

The break statement

To prematurely exit a loop, use the break statement:


            counter = 100
            while counter < 200:
                if counter % 7 == 0:
                    first_multiple = counter
                    break
                counter += 1
            

Looping while true

If you are brave, you can write while loops like this:


            counter = 100
            while True:
                if counter % 62 == 0:
                    first_multiple = counter
                    break
                counter += 1
            

⚠️ Be very sure that you're not coding an infinite loop!

Don't trust me? Ask Twitter!

Exercise

These are un-graded exercises you can do after the lecture to make sure you grok the basics:

Example: Prime factors

A prime number is an integer greater than 1 whose only factors are 1 and the number itself (e.g., 3, 5, 7, 11).


            def is_prime(n):
                """Return True iff N is prime."""
                return n > 1 and smallest_factor(n) == n

            def smallest_factor(n):
                """Returns the smallest value k>1 that evenly divides N."""
                ???

            def print_factors(n):
                """Print the prime factors of N."""
                ???
            

Let's implement them together.