Python in 30 Days - Day 12

Learning Python in 30 Days by going through a refresher course. Day 12 involves iterators and generators.

Day 12 was about iterators and generators. An iterator is any object that knows how to produce the next value when asked. Python’s for loop just keeps calling “give me the next one” until there’s nothing left. A generator produces values on demand — one at a time, only when asked. It pauses between values and resumes where it left off.

The Challenge:

Stay in the restaurant world:

  1. Write a generator function menu_items(menu) that yields one (item, price) tuple at a time from a menu dictionary

  2. Write a generator function filtered_menu(menu, max_price) that yields only items at or under max_price — without building a filtered list first

  3. Write a generator function order_summary(orders) that takes a list of order dictionaries like:

pythonorders = [
    {"item": "Burger", "quantity": 2, "price": 15},
    {"item": "Fries", "quantity": 3, "price": 5},
    {"item": "Milkshake", "quantity": 1, "price": 9},
]

And yields a formatted summary string for each order: “2x Burger — $30.00”

  1. Write a generator function running_total(orders) that yields the cumulative total after each item is added — so if you add a $30 item then a $15 item, it yields 30, then 45

  2. Consume all four generators and print their output cleanly — remember, you can only iterate a generator once, so plan accordingly

My Code:

def menu_items(menu):

    for item, price in menu.items():
        yield item, price


def filtered_menu(menu, max_price):

    for item, price in menu.items():
        if price <= max_price:
            yield item, price


def order_summary(orders):

    for order in orders:
        total_item_price = order["quantity"] * order["price"]
        yield f"{order['quantity']}x {order['item']} — ${total_item_price:.2f}"


def running_total(orders):

    total = 0
    for order in orders:
        total += order["quantity"] * order["price"]
        yield total


restaurant_menu = {"Burger": 15, "Fries": 5, "Milkshake": 9, "Steak": 35, "Soda": 3}

customer_orders = [
    {"item": "Burger", "quantity": 2, "price": 15},
    {"item": "Fries", "quantity": 3, "price": 5},
    {"item": "Milkshake", "quantity": 1, "price": 9},
]

print("=== 1. All Menu Items ===")

for item, price in menu_items(restaurant_menu):
    print(f"{item}: ${price}")

print("\n=== 2. Filtered Menu (Under or at $10) ===")

for item, price in filtered_menu(restaurant_menu, max_price=10):
    print(f"{item}: ${price}")

print("\n=== 3 & 4. Order Summary & Running Total ===")

summary_gen = order_summary(customer_orders)
total_gen = running_total(customer_orders)

for summary, current_total in zip(summary_gen, total_gen):
    print(f"Added: {summary} | (Running Bill Total: ${current_total:.2f})")

Running the Code:

=== 1. All Menu Items ===
Burger: $15
Fries: $5
Milkshake: $9
Steak: $35
Soda: $3

=== 2. Filtered Menu (Under or at $10) ===
Fries: $5
Milkshake: $9
Soda: $3

=== 3 & 4. Order Summary & Running Total ===
Added: 2x Burger — $30.00 | (Running Bill Total: $30.00)
Added: 3x Fries — $15.00 | (Running Bill Total: $45.00)
Added: 1x Milkshake — $9.00 | (Running Bill Total: $54.00)

That’s a wrap. Day 13 is about context managers.