Generators in Python are functions that use the `yield`

keyword instead of `return`

to return an iterator. Unlike normal functions that return all values at once, generators return one value at a time and then wait for the next call to generate the next value. This makes generators memory-efficient and can be useful when working with large data sets or generating an infinite sequence of values.

The generator function is defined like a normal function, but instead of using the `return`

keyword to return a value, it uses `yield`

keyword to produce a sequence of values.

#### Example:

def fibonacci(n): a, b = 0, 1 for i in range(n): yield a a, b = b, a + b # Using the generator function to print the fibonacci sequence for i in fibonacci(10): print(i)

In the above code, `fibonacci()`

is a generator function that returns an iterator. When the function is called, it does not start executing immediately. Instead, it returns an iterator object that can be used to iterate over the sequence of values generated by the function. The for loop is used to iterate over the sequence of values and print them.

Generators can also be used to generate an infinite sequence of values. For example, the following generator function generates an infinite sequence of even numbers:

def even_numbers(): n = 0 while True: yield n n += 2 # Using the generator function to print the first 10 even numbers count = 0 for i in even_numbers(): if count == 10: break print(i) count += 1

In the above code, `even_numbers()`

is a generator function that generates an infinite sequence of even numbers. The while loop generates a sequence of even numbers by incrementing the value of `n`

by 2 on each iteration, and the `yield`

keyword is used to return the current value of `n`

. The for loop is used to print the first 10 even numbers generated by the generator function.

Generators can also be used to chain multiple iterators together or to filter elements from an iterator. This can be achieved using the `yield from`

statement. Here’s an example that demonstrates how to use `yield from`

to chain two iterators together:

def chain(iter1, iter2): yield from iter1 yield from iter2 # Using the generator function to chain two iterators for i in chain([1, 2, 3], [4, 5, 6]): print(i)

In the above code, `chain()`

is a generator function that chains two iterators together. The `yield from`

statement is used to yield values from the first iterator and then yield values from the second iterator. The for loop is used to iterate over the combined arrangement of values generated by the generator function.