Python Generators: yield
In this post i will try to explain the basics of python generator. And will be writing another post to cover advance use and some debugging techniques.
In python, generator is part of functional programming. A generator is an object that returns a value on each call of its
next() method until it raises
It’s introduced in PEP255 and offers really easy way to implement Iterator Protocol.
def a_generator(): yield 1
Yes, thats all it takes to write a python generator function. It’s just like a normal python function contains
yield statement instead of
return. Python will detect the
yield statement and tag the function as a generator.
When function’s execution reaches a
yield statement, it returns a value with a
return statement, but in the case of generator python interpreter will save a stack reference, which will be used to resume the function’s execution when
next() method is called next time.
def a_generator(): yield 'ready' yield 'steady' yield 'go' gen_obj = a_generator() next(gen_obj) # returns 'ready' next(gen_obj) # returns 'steady' next(gen_obj) # returns 'go' next(gen_obj) # raises StopIteration exception
Generators in python are considered slightly advanced topic because of their nature of execution. But they can come really handy in some scenario and helps to keep your code clean while delivering efficient solution to the problem. For example, if you have a function which generates and returns a list of items. This can be simplified using generators.
Refactoring tip using yield:
def get_best_items(items, best_item_rank=8): best_items_list =  for item in items: if item.rank >= best_item_rank: item_list.append(item) return best_items_list
Above function can be simplified using generator as below:
def get_best_items(items, best_item_rank=8): for item in items: if item.rank >= best_item_rank: yield item
for loop is smart enough to catch
StopIteration exception if raised and terminates the loop gracefully.
for item in get_best_items(items): print(item)
So by refactoring the function using yield,
best_items_list =  is not required, thus
item_list.append(item) should be gone as well. And finally we got our nice and clean function by removing some not so required code for this purpose.