A generator in Python is a special kind of function that returns an iterator and lets you produce values one at a time using yield. Instead of creating and storing an entire sequence in memory, a generator creates each value only when it is requested (lazy evaluation), making it very memory-efficient, especially for large datasets or streams of data.
yield instead of return.next() and StopIteration – used to manually pull values from a generator.A generator function looks like a normal function but uses yield to produce a sequence of values. Each time the generator yields, its state is saved, and execution resumes from the same point when the next value is requested.
A generator expression is similar to a list comprehension, but uses parentheses instead of square brackets. It returns a generator object that produces items one by one.
The built-in next() function can be used to manually advance a generator. When there are no more values to produce, the generator raises a StopIteration exception internally.
# generator that yields numbers 0 to 4
def my_generator():
for i in range(5):
yield i
# create generator object
gen = my_generator()
# iterate and print values
for value in gen:
print(value)
# generator expression for squares
gen_exp = (x * x for x in range(5))
# iterate through generator
for value in gen_exp:
print(value)
gen = (x * x for x in range(3))
print(next(gen)) # 0
print(next(gen)) # 1
print(next(gen)) # 4
# next(gen) now will raise StopIteration
0 1 2 3 4 are printed one by one. The generator yields each i, and the for loop consumes those values.0 1 4 9 16 are printed. The values are computed lazily as the loop iterates.next() example, three calls to next(gen) return 0, 1, and 4. A fourth call would raise StopIteration because the generator has no more items to yield.Notice that at no point is a full list stored in memory. Each value is generated only when needed, which is the core advantage of using generators.
yield, not return for multiple values.StopIteration if you manually use next(), or simply rely on a for loop.next() a few times on a generator and then switch to a for loop to see how it behaves when exhausted.