Ranges & Controls

Jed Rembold & Fred Agbo

January 27, 2025

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

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

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

Class Activity?

// reveal.js plugins