Day 27 - Transition to Python 3
Traversing and Transforming Lists in Python vs. Pyret
1. Introduction (10 minutes)
- Overview:
- Recap the previous lecture on creating and processing lists in Python.
- Explain that today we focus on traversing lists to compute summary values and to produce new lists.
- Learning Goals:
- Understand the use of Python’s imperative for loops for list traversal.
- Contrast Python’s for loops with both Pyret’s recursive list processing and its
for each
loops.
- Do Now:
- Ask: “How would you sum a list of numbers in Pyret using recursion? How about using a for‑each loop?”
- Quick discussion.
2. Traversing Lists Using For Loops in Python
- Example: Summing a List
-
Python Code:
def sum_list(num_list: list) -> float:
run_total = 0
for num in num_list:
run_total = run_total + num
return run_total -
Discussion:
- Compare with Pyret’s
for each
version:
fun sum-list(num-list: List<Number>) -> Number block:
var run-total = 0
for each(num from num-list):
run-total := run-total + num
end
run-total
end- And Pyret's recursive version:
fun sum-list(numlist :: List<Number>) -> Number:
cases (List) numlist:
| empty => 0
| link(fst, rst) => fst + sum-list(rst)
end
end
- Compare with Pyret’s
-
- Order of Processing:
- Discuss that Python’s for loop processes elements in order (left-to-right) and that this may differ from a recursive approach that “unrolls” from the base case upward.
- Interactive Exercise:
- Ask students to trace
sum_list([5, 2, 7, 3])
by listing the successive values ofrun_total
.
- Ask students to trace
3. Producing New Lists via For Loops
- Example: Extracting Words Containing “z”
- Python Code:
def all_z_words(word_list: list) -> list:
z_list = [] # start with an empty list
for wd in word_list:
if "z" in wd:
# Prepend wd (or append if preferred)
z_list = [wd] + z_list
return z_list - Discussion:
- Compare with a Pyret version using
for each
:fun all-z-words(wordlist :: List<String>) -> List<String>:
var result = empty
for each(wd from wordlist):
if string-contains(wd, "z"):
result := [list: wd] + result
end
end
result
end
- Compare with a Pyret version using
- Interactive Exercise:
- Ask: “What order will the words appear in? How might you modify the code to preserve the original order?”
- Python Code:
- Additional Topic:
- Briefly mention that while Python’s for loops work well for linear lists, they cannot directly traverse non-linear (tree) data without additional structure.
4. Summary: List-Processing Templates in Python vs. Pyret
- Template for Python List Processing:
- General Template:
def func(lst: list):
result = <base_value>
for item in lst:
result = <combine>(item, result)
return result - This can be directly translated to Pyret's
for each
loops. - Compare with Pyret’s recursive template:
fun func(lst :: List<T>) -> R:
cases (List) lst:
| empty => <base_value>
| link(first, rest) => <combine>(first, func(rest))
end
end - The recursive template is more general, as it will work with data like trees.
- General Template:
- Discussion:
- Emphasize that Python’s imperative style uses mutable variables and explicit
for loops, Pyret can do this with
for each
, but also has good support for recursion.
- Emphasize that Python’s imperative style uses mutable variables and explicit
for loops, Pyret can do this with
- Do Now (Reflection):
- Ask students: “Which approach do you find more intuitive for list processing and why?”
5. Wrap-Up and Exit (10 minutes)
- Recap Key Points:
- We have seen three ways to process lists:
- Recursively (Pyret style using cases),
- Imperatively (Pyret using for‑each loops), and
- Imperatively in Python (using for loops and mutable accumulators).
- Each student writes a short paragraph (3–4 sentences) comparing the recursive approach in Pyret with the for loop approach in Python for list processing, noting strengths and weaknesses.
- We have seen three ways to process lists: