The yield
keyword in Python is used in the context of generators. It's specifically used in a function to turn it into a generator. When the function is called, it doesn't execute immediately as a regular function would. Instead, it returns a generator object, which you can iterate over to get values one at a time.
Here's a simple example to illustrate the use of yield
:
def my_generator():
yield 1
yield 2
yield 3
Using the generator
gen = my_generator()
print(next(gen))
print(next(gen))
print(next(gen))
Output is
1
2
3
In this example, my_generator
is a generator function. When you call it, it returns a generator object. The next()
function is then used to get the values one at a time. When you reach the end of the generator, it raises the StopIteration
exception.
The crucial part is that the state of the generator function is remembered between calls. It doesn't start from the beginning every time; it resumes from where it left off.
Use Cases of yield
:
Memory Efficiency: If you need to generate a large sequence of values but don't want to store them all in memory at once, using
yield
in a generator is more memory-efficient.Iterative Processing: It's useful when you are processing items in an iterative manner, and you don't need to compute all the items at once.
Infinite Sequences: Generators can be used to represent infinite sequences, like all even numbers or all prime numbers, where you might not want to compute all values upfront.
Stateful Generation: Generators can maintain state between calls, which can be handy for certain algorithms where maintaining state is essential.
Example: Fibonacci Sequence using yield
:
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
Using the generator
fib_gen = fibonacci()
print(next(fib_gen))
print(next(fib_gen))
print(next(fib_gen))
print(next(fib_gen))
... and so on
Output is
0
1
1
2
In this example, the fibonacci
generator generates the Fibonacci sequence indefinitely without computing all values upfront.
The use of yield
is a powerful tool for creating iterators and generators, making your code more memory-efficient and flexible.
If you're working with a generator, you can use a for
loop to iterate through its values. Here's an example using the my_generator
function from the previous example:
def my_generator():
yield 1
yield 2
yield 3
Using a for loop with the generator
for value in my_generator():
print(value)
This will output:
1
2
3
In this case, the for
loop is automatically calling next()
behind the scenes and catching the StopIteration
exception when the generator is exhausted.
For the Fibonacci sequence example:
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
Using a for loop with the generator
fib_gen = fibonacci()
for _ in range(5): # Print the first 5 Fibonacci numbers
print(next(fib_gen))
This will output the first 5 Fibonacci numbers:
0
1
1
2
3
In practice, using a for
loop with generators simplifies the code and makes it more readable when you want to iterate over the values generated by the generator.