-
Section 1: Getting Started
-
Section 2: Core Syntax and Data Types
-
Section 3: Collections
-
39: Set Operations: Union, Intersection, Difference
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Turtle Graphics and Early Practice Projects
-
Section 7: Working with Files and I/O
-
Section 8: Regular Expressions
-
Section 9: Object-Oriented Python
-
Section 10: Error Handling
-
Section 11: Modules and Packages
-
Section 12: Iterators, Generators, and Functional Tools
-
Section 13: Decorators and Metaprogramming
-
Section 14: Concurrency and Parallelism
-
Section 15: Working with Dates, Times, and Numbers
-
Section 16: Standard Library Deep Dive I: Data Structures
-
Section 17: Standard Library Deep Dive II: System and Introspection
-
Section 18: Standard Library Deep Dive III: Security and Encoding
-
Section 19: Standard Library Deep Dive IV: Text and Data Utilities
-
Section 20: Networking and Web Basics
-
Section 21: Working with Databases
-
Section 22: Testing and Quality
-
Section 23: Advanced Typing
-
Section 24: Context Managers and Resource Handling
-
Section 25: Text, Unicode, and Binary Data
-
Section 26: More Functional and Iteration Tools
-
Section 27: Data Validation and Configuration
-
Section 28: Working with Images and Media
-
Section 29: Property-Based and Documentation Testing
-
Section 30: Packaging and Deployment
-
Section 31: Performance and Internals
-
Section 32: Design Patterns in Python
-
Section 33: GUI Programming
-
Section 34: Security Basics
-
Section 35: Data Structures and Algorithms
-
Section 36: Practical Projects
-
Section 37: Capstone Projects
-
Section 38: Interview and Algorithm Practice
-
Section 39: Writing Idiomatic Python
185: Practice Exercise: Building a Custom Fibonacci Generator
Imagine you have a magic vending machine. Unlike a normal one, it doesn't hold a giant warehouse of pre-made snacks inside. Instead, it has a small notebook and a tiny kitchen. Every time you press the button, the machine looks at its notebook to see what it gave you last, cooks one fresh snack based on that information, hands it to you, and then pauses. It doesn't cook the next snack until you press the button again. It doesn't matter if you want ten snacks or ten million; the machine only ever needs enough space for that one notebook and one snack at a time.
That's exactly how a Python generator works. Instead of calculating a massive list of numbers and shoving them into your computer's RAM (which is the "warehouse" approach), a generator calculates the next value on the fly and then "freezes" its state until you ask for more. In this lesson, we're applying this to the Fibonacci sequence.
Mapping the Magic Machine to Code
Let's look at how that vending machine logic translates directly into a Fibonacci generator:
- The Button: This is the
next()function or aforloop. It's the signal that tells the generator, "Okay, wake up and give me the next value." - The Notebook: These are the local variables inside your function (like
aandb). They keep track of where the sequence left off so the function doesn't have to start from zero every time. - The Delivery: This is the
yieldkeyword. Unlikereturn, which kills the function and sends back a value,yieldsends the value back but keeps the function alive in a paused state.
def fibonacci_generator():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
Why we avoid the "List Trap"
I've seen a lot of developers start by writing a function that appends Fibonacci numbers to a list and returns that list. That works fine if you want the first 20 numbers. But what if you need the 2,000,000th number? If you use a list, your program will likely hang or crash as it tries to allocate a massive chunk of memory to hold every single preceding number. I've been there—it's a frustrating way to spend an afternoon.
By using yield, the memory footprint remains constant. Whether you're on the 5th number or the 5 billionth, the generator only cares about two integers at any given moment. It's lean, it's fast, and it's the "professional" way to handle infinite or massive sequences.
Taming the Infinite Loop
You'll notice I used while True in the example above. Normally, an infinite loop is a bug. Here, it's a feature. Since the yield keyword pauses the execution, the loop doesn't actually "run away" and freeze your computer. It only advances one step every time you iterate over it. To prevent it from running forever in your actual app, you just use a break condition inside your loop or use a tool like itertools.islice to tell Python exactly when to stop asking the vending machine for more snacks.
📋 Practical Task
Building a Limited-Range Fibonacci Generator
Your task is to create a generator function called fibonacci_until(limit). Unlike the infinite generator we discussed, this one should stop producing numbers once the value exceeds the limit provided as an argument.
Requirements:
- The function must use the
yieldkeyword. - It should take one parameter:
limit(an integer). - It should yield Fibonacci numbers starting from 0 and 1.
- As soon as the next number in the sequence is greater than the
limit, the generator should stop.
Example Usage:
for num in fibonacci_until(10):
print(num)
# Expected output: 0, 1, 1, 2, 3, 5, 8
There are no comments for now.