Ranges & Controls

Jed Rembold & Fred Agbo

January 31, 2024

Announcements

  • Problem Set 2 is posted and due on Monday next week at 10 pm
    • Feedback for PS1 will be ready by next week!
  • I will strongly recommend making your submission as is on due dates
  • Policy for unexcussed late submissions will attract losing points as follows:
    • 10% for 24 hours late submission.
    • 20% for 48 hours late submission.
    • 50% for a week late submission.
    • Beyound 1 week may not earn points
  • We will be concluding chapter 2 of the text today. Hope eveyone is reading the text along
  • Link to Polling https://www.polleverywhere.com/agbofred203

Review Question

What is the printed value of A in the code below?

>>> A = 10
>>> B = 5 % 3
>>> C = A * B ** B
>>> A -= B + A // 2
>>> A, B, C = C, A, B
>>> print(A)
??
  1. 3
  2. 12
  3. 30
  4. 40

Boolean Expressions

  • Python defines two types of operators that work with Boolean data: relational operators and logical operators

  • Relational operators compare values of other types and produce a True/False result:

    == Equals != Not equals
    < Less than <= Less than or equal too
    > Greater than >= Greater than or equal to
  • Be careful! == compares two booleans. A single = assigns a variable. The odds are high you’ll use one when you meant the other at least once this semester!

The Vulcan Way

  • Logical operators act on Boolean pairings

    Operator Description
    A and B True if both terms True, False otherwise
    A or B True if any term is True, False otherwise
    not A True if A False, False if A True (opposite)
  • Order of operations follows parentheses and then proceeds left to right
  • Careful that or is still True if both options are True
  • Similarly, careful with combining not with and and or
    • “Not A or B” in common English is not the same as not A or B

Shorting the Circuit

  • Python evaluates and and or operators using a strategy called short-circuit mode
  • Only evaluates the right operand if it actually needs to
    • Example: if n=0, then the x % n == 0 is never actually checked in the statement

      n != 0 and x % n == 0

      since n != 0 already is False and False and anything is always False

  • Can use short-circuit to prevent errors: the above x % n == 0 statement would have erred out if n=0

Input: input

  • To retrieve data from a user, we can use Python’s built-in input() function

  • The form will generally look like:

    variable = input(prompt_text)
    • variable is the variable name you want to assign the user’s typed input to
    • prompt_text is the string that will be displayed on the screen to communicate to the user what they should be doing
  • The input() function always returns a string

    • If you want to get an integer from the user, you will need to convert it yourself after retrieving it

      num = int(input('Pick a number between 1 and 10: '))

Sentinels

  • Many programs in programming can be approached similarly by using a particular idiom or pattern
  • A common one with repetition is to use a variable to keep track of the loop state until something particular happens (the sentinel is triggered)
  • Using a variable to track/control a loop state

    finished = False
    while not finished:
        line = input("Enter a number: ")
        if line == "":
            finished = True
        else:
            print(line)
  • Building up a sequence from nothing using concatenation

    new = ""
    word = "fantastical"
    i = 0
    while i < len(word):
        new += word[i]
        i += 2

Running a Program

  • Python programs specify what part of the code is supposed to be executed when a program is run using a few special lines at the end of the program

    if __name__ == '__main__':
        function_to_run()
    • function_to_run is the name of whatever function you want to execute when the program is run directly
  • Patterns of this sort are commonly called boilerplate

    • Less important to fully understand all the pieces of it now
    • Is important to understand what it is doing and how to implement it correctly

Sample Program


NUM_ODDS = 100 # Constant, so using all caps

def print_odds():
    """
    Prints the first NUM_ODDS odd numbers 
    starting at 1.
    """
    value = 1
    for i in range(NUM_ODDS):
        print(value)
        value += 2

if __name__ == '__main__':
    print_odds()

Visiting the library(ies)

  • A huge strength of Python is that it offers a very large number of code collections called libraries
    • Can save you the effort from writing that code yourself!
  • Requires you to import that library, which can take several different forms
    • Most common is to use import to grab everything in a library

      import math
      • You must then access any function in that library using its fully qualified name, which includes the library name (var = math.sqrt(4))
    • Can also use from ... import to grab specific functions from the library

      from math import sqrt
      • You do not need to use the library name then when you call it (var = sqrt(4))

Useful math definitions

Code Description
math.pi The mathematical constant \(\pi\)
math.e The mathematical constant \(e\)
math.sqrt(x) The square root of x
math.log(x) The natural logarithm of x
math.log10(x) The base 10 logarithm of x
math.sin(x) The sine of x in radians
math.cos(x) The cosine of x in radians
math.asin(x) The arcsin of x
math.degrees(x) Converts from radians to degrees
math.radians(x) Converts from degrees to radians

Extra if functionality

  • Karel could only use if and else
  • Python also supports as elif statement
  • Let’s you chain together multiple mutually exclusive condition checks
  • You can include as many elif chained statements as you want
if condition_1:
    # Run this code if 
    # condition 1 is true
elif condition_2:
    # This code runs if 
    # condition 1 is false
    # but condition 2 is true
elif condition_3:
    # Runs if both condition 1
    # and 2 fail but condition
    # 3 is true
else:
    # This code runs if 
    # all above conditions 
    # fail

For Loop Anatomy

  • We have already seen for loops in Karel, but let’s expand on their use:

  • The more general syntax of a for loop looks like:

    for variable_name in sequence:
        # code to loop over
    • variable_name is a variable name that will be assigned every value in the sequence over the course of the loop
    • sequence is any expression that produces a variable that supports iteration
      • We’ve already seen range() fill this role
      • Any sequence works though! So strings and lists can also be looped over!

The range() iterable

  • Need an easy way to produce or describe a range of numeric values
  • The built-in range() function handles this and produces the needed iterable object
  • Takes 1, 2, or 3 arguments:
    • Start (default 0): where to start the sequence at
    • Stop (mandatory): the sequence ends just below this value (does not include it!)
    • Step (default 1): what value the sequence counts by

Be careful, the range function will stop one step before the final stop value.

For ranging examples

  • Providing just a stop argument:

    for n in range(5):
        print(n)
  • Providing a start and stop:

    for n in range(1,11):
        print(n)
  • Providing a start, stop, and step:

    for n in range(10,0,-1):
        print(n)

Iterating over sequences

  • We can also use a for loop to iterate directly over a sequence of values

  • We can loop through a string or list to examine each individual character or element

  • Example of looping through a word to count occurrences of a given letter:

    def count_letters(letter, string):
        count = 0
        for character in string:
            if character == letter:
                count += 1
        return count

Test Yourself

  • It is easy to make mistakes when writing code
    • Syntax mistakes
    • Typos or operations mistakes
    • Overall conceptual mistakes
  • Given that making mistakes is entirely natural, it is also imperative that looking for mistakes become entirely natural
  • You known what the desired goal is for basically every problem in this class. Test your code!

Way of Testing

  • Run your code early and often
    • If your code is breaking at something early, it is not going to fix itself if you continue
  • Test outputs directly
    • Problems will generally give several example outputs of desired functions
    • For your own functions, you should know what you want them to be outputting
    • Run a function as isolated as you can make it after writing it, and ensure that it is performing as expected
  • Write code to test code
    • Wherever possible, I provide some automated tests that can be run
    • You can (and should) write your own tests as well. They need not be complicated!!

Assertions

  • You can use Python’s assert statement to write test functions, which take the form:

    assert condition

    where condition is any operation that returns a True or False

  • Assert statements “expect” a condition to yield a True, and if they do, nothing happens

    • No news is good news in this case
  • If an assert condition evaluates to False, an error is raised

  • Naming your test functions starting with the word test_ will make them automatically discoverable by other tools

Testing Example

  • Suppose we wanted to write some checks of the count_letters function from earlier
def test_count_letters():
    """ Runs several tests on the function count_letters """
    assert count_letters("z", "banana") == 0
    assert count_letters("a", "strawberry") == 1
    assert count_letters("A", "apple") == 0
    assert count_letters("e", "eerie") == 3
// reveal.js plugins