Python - Yield
Published:
yield
is a special keyword like return
. It can create an iterator in Python. If you want to get a value from an iterator, you need to use the next
function or a for
loop. Sometimes, we find that the list index can’t be used directly, map
and filter
output. It might mean that the output is an iterator yet to be called in the normal way.
hello = "Hello world!"
helloIter = iter(hello)
while True:
# when no val to return, next return deault "None"
nxt = next(helloIter, None)
if not nxt: break
print(nxt)
Also, we can save memory by using the iterator. The iterator returns a value once a time. Thus, we don’t need a local variable to store all the outputs. As soon as we require the value, we call the iterator which just maintains the function state. In addition to iter
, yield
is another way to create the iterator. Once we use yield
to return the value, we consider that function a generator (iterator).
def constructList(length: int) -> List[int]:
output = []
for num in range(1, length + 1):
output.append(num)
return output
for n in constructList(10000):
print(n)
def constructList(length: int) -> int:
for num in range(1, length + 1):
yield num
for n in constructList(10000):
print(n)
Usage
Leetcode 173. Binary Search Tree Iterator [medium] is a good example in practice. In the description, we know that it’s a BST problem. In-order-traversal can help us gain the element in ascending order. However, the problem wants to get the elements one by one, so we need to turn our DFS function into a generator (iterator).
class BSTIterator:
def __init__(self, root: Optional[TreeNode]):
self.root = root
self.iter = self.dfs(self.root)
self._cur = next(self.iter)
def dfs(self, node: Optional[TreeNode]):
if node:
yield from self.dfs(node.left)
yield node.val
yield from self.dfs(node.right)
def next(self) -> int:
result = self._cur
self._cur = next(self.iter, None)
return result
def hasNext(self) -> bool:
return (False if self._cur is None else True)
yield from generator
is equal to for v in generator: yield v
. We first need to get the elements from the left subtree. Second, return the current node value. The last one to return is the right subtree.