Python Loops

CSCI 1913 – Introduction to Algorithms, Data Structures, and Program Development
Adriana Picoral

Warm-up

  • What would the standard output look like after the code below has finished running?
  • What would the docstring for digits look like? (in other words, what does digits do?)
def digits(number):
    result = []
    while number > 0:
        result.insert(0, number % 10)
        number = number // 10
    return result

if __name__ == "__main__":
    for d in digits(104231):
        print(d)

while vs for loops

A while loop has a condition that needs to evaluate to False to get out of the loop:

n = 3
while n > 0:
  print(n)
  n = n - 1
3
2
1

A for loop uses a variable:

for n in range(3):
  print(n)
0
1
2

Definite vs. Indefinite loops

Definite loop: the number of iterations is known before the loop begins execution

Which type of loop is always definite? while or for loops?

while and for loops

  • A while loop runs until its a return statement inside the loop or the while condition is evaluated as false
  • For loops operate over an iterable object (range, list, string, set, tuple)
  • All for loops can be converted into while loops
  • Not all while loops can become for loops (definite loops can be converted to a while loop)
  • For loops are slightly faster
  • Python does NOT have do while loops (code block inside while loops can run zero times)

range

range(start, stop, step)

  • range is both a function and an object
  • range only works with integers
  • a range object represents a sequence of integer numbers
    • range(5) is a sequence of the numbers 0,1,2,3,4
    • it is not indexable in all versions of python (we will see indexing in a bit)

Quiz 01

You have 10 minutes to complete the quiz

  • No need for comments or doc strings, no need to include the tests in your solution, no need for if __name__
  • Just write your function and what’s inside the function
  • Raise your hand when you’re done, a TA will come and grab your completed quiz

HINT: use the keyword def to define a function

Exercise

Write a python function called factorial that uses a loop (for or while, up to you) to calculate factorial of a non-negative integer n (n!)

A factorial is the product of a given positive integer and all the positive integers smaller than it down to 1:

\(5! = 5 × 4 × 3 × 2 × 1 = 120\)

The factorial of 0 (0!) is defined as 1.

Submit your solution (name your file loop_factorial.py) to gradescope

assert factorial(0) == 1
assert factorial(5) == 120
assert factorial(7) == 5040

Solution 1 – for loop

def factorial(n):
  result = 1
  for number in range(2, n+1):
    result *= number
  return result

if __name__ == "__main__":
  assert factorial(0) == 1
  assert factorial(5) == 120
  assert factorial(7) == 5040
  print("Passed all tests")
Passed all tests

Solution 2 – for loop

def factorial(n):
    if n == 0:
        return 1
    
    result = 1
    for i in range(1, n + 1):
        result *= i
    
    return result

Solution 3 – while loop

def factorial(n):
  result = 1
  while n > 0:
    result *= n
    n-=1
  return result

Solution 4 – while loop

def factorial(n):
    if n == 0:
        return 1
    
    result = 1
    i = 1
    while i <= n:
        result *= i
        i += 1
    
    return result

Sequences

Sequence: an ordered collection of items

  • strings, tuples, lists
  • can hold duplicate values
  • can be indexed (indexes start at zero)
  • built-in len() function
  • strings and tuples are immutable and lists are mutable

Tuples

Tuple can hold repeated values

my_tuple = ("apple", "banana", "pear", "banana")
my_tuple[1] # item at index 1
my_tuple[1:3] # slice from second to third item
('banana', 'pear')

… can hold any type (including tuples, for nested tuples)

my_tuple = (("apple", "banana"), ("pear", "banana", 3), 4)
my_tuple[1] # item at index 1
my_tuple[1:3] # slice from second to third item
(('pear', 'banana', 3), 4)

Tuples

There are several edge cases for tuple literals

  • An empty tuple is just to parentheses containing nothing ()

  • A tuple with only one item must have a trailing comma tup_of_1 = (50,)

  • You can always have a trailing comma tup_t = (8, "6", 7, 5, "3", "09", )

  • If you have a bunch of comma separated values without parentheses they may also be interpreted as a tuple.

    vals = 4, 5, 6, 3.3, "Tuple"

Tuple constructor

my_chars = tuple("abcdef")
my_chars[2]
'c'

Tuple operators

  • Concatenation: (2, 3) + (1, 2, 3)
  • Multiplication: (2,) * 3

Return tuples in a python function

def min_max(numbers):
  return min(numbers), max(numbers)

if __name__ == "__main__":
  test_numbers = (-2, 100, 3, -23, 0)
  print(min_max(test_numbers))
  
  # unpack tuples into multiple variables
  min_value, max_value = min_max(test_numbers)
  print(min_value)
  print(max_value)
(-23, 100)
-23
100

Strings

Same operators as tuples

my_string = "apple"
my_string[3]
my_string[1:4]
'ppl'

for “each” loops in Python

Looping over a sequence with an index:

my_string = "apple"
for i in range(len(my_string)):
  print(my_string[i])

Looping over a sequence without an index:

my_string = "apple"
for char in my_string:
  print(char)

Exercise

Write a python function called hex_to_rgb that gets as argument a hex code in the string format "#F54927" and returns the equivalent RGB code in a tuple of integers format (245, 73, 39)

Hint: The base of a hexadecimal system is 16, we want to convert a two digit hex code to decimal integer. For example, you can convert "CF" to python using the int() built-in function like so int("CF", 16)

Submit your solution colors.py to the in-class exercise in gradescope.

Solution

def hex_to_rgb(hex_string):
    red = hex_string[1:3]
    blue = hex_string[3:5]
    green = hex_string[5:7]
    return int(red, 16), int(blue, 16), int(green, 16)
  
if __name__ == "__main__":
    assert hex_to_rgb("#F54927") == (245, 73, 39)
    assert hex_to_rgb("#000000") == (0, 0, 0)
    assert hex_to_rgb("#FFFFFF") == (255, 255, 255)
    assert hex_to_rgb("#70B578") == (112, 181, 120)

    print("Passed all tests")
Passed all tests

Exercise

Write a python function that determines whether a whole number greater than one is prime. A prime is divisible only by itself and 1 (not a product of two smaller natural numbers). Submit your python script prime.py to gradescope.

Test the remainder of the division with all primes up to the square root of the argument n.

Test cases:

if __name__ == "__main__":
    assert is_prime(2) == True
    assert is_prime(4) == False
    assert is_prime(29) == True
    assert is_prime(53) == True
    assert is_prime(54) == False

    print("Passed all tests")

Expansion

Add to your previous solution a python function called get_primes that takes a whole number greater than one as argument and returns a tuple with all integers that are prime up (and including) n.

Test cases:

if __name__ == "__main__":
    assert get_primes(2) == (2,)
    assert get_primes(4) == (2, 3)
    assert get_primes(29) == (2, 3, 5, 7, 11, 13, 17, 19, 23, 29)
    assert get_primes(53) == (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53)
    assert get_primes(54) == (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53)

    print("Passed all tests")