Lab

11.3.2. Lab#

  • Use this lab to practice the chapter’s coding skills in runnable Python code.

  • Sign in from the account menu before you start working on the lab.

  • Launch Live Code (the rocket) to write and run code in the coding cells.

  • Multiple submissions are allowed. The highest score is kept.

### Question 1: Custom Iterator: Threshold Filter
# A sales team wants to review only the transactions above a threshold.
# Implement a class AboveThreshold(values, threshold) with __iter__/__next__
# that returns, one at a time, only the values greater than threshold.
# Skip values at or below threshold instead of stopping on them.
# Raise StopIteration once every value has been checked.
# Collect the filtered values with list(), then print exactly these two lines:
# Sales above 1000: [1200, 2100, 1600]
# Count above 1000: 3
sales = [1200, 850, 2100, 430, 975, 1600]
### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
sales = [1200, 850, 2100, 430, 975, 1600]

class AboveThreshold:
    def __init__(self, values, threshold):
        self.values = list(values)
        self.threshold = threshold
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        while self.index < len(self.values):
            value = self.values[self.index]
            self.index += 1
            if value > self.threshold:
                return value
        raise StopIteration

big_sales = AboveThreshold(sales, 1000)
result = list(big_sales)
print("Sales above 1000:", result)
print("Count above 1000:", len(result))
Sales above 1000: [1200, 2100, 1600]
Count above 1000: 3
### Question 2: Custom Iterator: Batch Sales Data
# Large sales exports are processed in fixed-size batches.
# Implement a class Batched(values, size) with __iter__/__next__ that
# returns successive lists (batches) of length size from values.
# The final batch may be shorter than size if values does not divide evenly.
# Raise StopIteration once every value has been placed in a batch.
# Loop over Batched(sales, 2) with a for loop and print each batch (one per line):
# [1200, 850]
# [2100, 430]
# [975, 1600]
sales = [1200, 850, 2100, 430, 975, 1600]
### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
sales = [1200, 850, 2100, 430, 975, 1600]

class Batched:
    def __init__(self, values, size):
        self.values = list(values)
        self.size = size
        self.index = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.index >= len(self.values):
            raise StopIteration
        batch = self.values[self.index:self.index + self.size]
        self.index += self.size
        return batch

for batch in Batched(sales, 2):
    print(batch)
[1200, 850]
[2100, 430]
[975, 1600]
### Question 3: Generator Function: Running Maximum
# Write a generator function running_max(numbers) that yields the
# largest value seen so far after each element (a running maximum).
# Example: running_max([1, 5, 3, 8]) yields 1, 5, 5, 8.
# Collect the results with list() on the sales data and print exactly:
# [1200, 1200, 2100, 2100, 2100, 2100]
sales = [1200, 850, 2100, 430, 975, 1600]
### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
sales = [1200, 850, 2100, 430, 975, 1600]

def running_max(numbers):
    current_max = None
    for n in numbers:
        if current_max == None or n > current_max:
            current_max = n
        yield current_max

print(list(running_max(sales)))
[1200, 1200, 2100, 2100, 2100, 2100]
### Question 4: Generator Expressions with islice, any, and all
# Use a generator expression to compute a 10% discount on each sale:
# round(s * 0.9, 2) for each s in sales.
# Use itertools.islice to take only the first 3 discounted values.
# Use any() with a generator expression to check if any sale exceeds 1000.
# Use all() with a generator expression to check if every sale exceeds 400.
# Print exactly these three lines:
# First three discounted: [1080.0, 765.0, 1890.0]
# Any sale over 1000: True
# All sales over 400: True
import itertools

sales = [1200, 850, 2100, 430, 975, 1600]
### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
import itertools

sales = [1200, 850, 2100, 430, 975, 1600]

discounted_gen = (round(s * 0.9, 2) for s in sales)
first_three = list(itertools.islice(discounted_gen, 3))
any_over_1000 = any(s > 1000 for s in sales)
all_over_400 = all(s > 400 for s in sales)

print("First three discounted:", first_three)
print("Any sale over 1000:", any_over_1000)
print("All sales over 400:", all_over_400)
First three discounted: [1080.0, 765.0, 1890.0]
Any sale over 1000: True
All sales over 400: True
### Question 5: Infinite Generator with itertools.islice
# Write a generator function grow_sales(base, rate) that models
# compound growth: it yields base, then repeatedly multiplies the
# previous value by (1 + rate) and yields the result, forever (while True).
# Round each yielded value to 2 decimal places.
# Always bound consumption of an infinite generator with itertools.islice
# so the loop terminates.
# Take the first 5 values from grow_sales(1000, 0.1) and print exactly:
# Projected sales: [1000, 1100.0, 1210.0, 1331.0, 1464.1]
import itertools
### Your code starts here.



### Your code ends here.

Hide code cell source

### Solution
import itertools

def grow_sales(base, rate):
    value = base
    while True:
        yield value
        value = round(value * (1 + rate), 2)

first_5 = list(itertools.islice(grow_sales(1000, 0.1), 5))
print("Projected sales:", first_5)
Projected sales: [1000, 1100.0, 1210.0, 1331.0, 1464.1]