Yield From In Python

Overview:

  • In Python, the yield statement of the form yield from <expression> enables generator functions to delegate a portion of code with yield <expression> to a subgenerator in a seamless way, forming a chain of generators and subgenerators.
  • The absence of "yield from" in Python will make it difficult working with a chain of generators (if only the form yield <expression> is used), as each generator object in the chain needs to be iterated explicitly.
  • Without "yield from", communicating with the inner generators using send() and throw() becomes more complex.

Example 1:

# Define class Book
class Book:
    def __init__(self, title, chapter):
        self.myTitle     = title
        self.myChapters     = chapters

# Define class Chapter
class Chapter:
    def __init__(self, title, sections):
        self.myTitle = title
        self.mySections = sections

# Create chapters of the book
chapter1Sections = ["Chapter1Section1", "Chapter1Section2"]
chapter1 = Chapter("Chapter1", chapter1Sections)

chapter2Sections = ["Chapter2Section1", "Chapter2Section2"]
chapter2 = Chapter("Chapter2", chapter2Sections)

chapter3Sections = ["Chapter3Section1", "Chapter3Section2"]
chapter3 = Chapter("Chapter3", chapter3Sections)

chapter4Sections = ["Chapter4Section1", "Chapter4Section2"]
chapter4 = Chapter("Chapter4", chapter4Sections)

# Create a book
chapters = [chapter1, chapter2, chapter3, chapter4]
book = Book("Title of the Book", chapters)

# Generator function that delegates to a subgenerator 
def PrintBook(book):
    print(book.myTitle)
    for chapter in book.myChapters:
        chapterTitle = chapter.myTitle         
        print(chapterTitle)
        chapter = yield from GetChapter(chapter) # delegate

# Subgenerator function
def GetChapter(chapter):
    for section in chapter.mySections:
        yield section

# Create a generator object
bookPrintFunction = PrintBook(book)

# Navigate the generator
for item in bookPrintFunction:
    print(item)

Output:

Title of the Book

Chapter1

Chapter1Section1

Chapter1Section2

Chapter2

Chapter2Section1

Chapter2Section2

Chapter3

Chapter3Section1

Chapter3Section2

Chapter4

Chapter4Section1

Chapter4Section2

Example 2:

The Python example traverses a linked list which is a recursive data structure, using yield from and prints the contents of the linked list. 

# Example Python program that creates a linked list
# and prints its contents using a generator and 
# a subgenerator(using yield and yield from)

# Define the node of the linked list
class Node:
    def __init__(self, value):
        self.value         = value
        self.nextNode     = None

# Define the linked list
class LinkedList:
    def __init__(self):
        self.head = None
        self.tail = None

    # Function to insert a node at the end of the 
    # linked list    
    def insert(self, val):
        node = Node(val)

        if self.head == None and self.tail == None:
            self.head = node 
            self.tail = node 
            return
        
        self.tail.nextNode = node
        self.tail = node

    # Generator function delegating to the same subgenerator
    # recursively
    def listvalues(self, node):
        if node == None:
            return
        yield node.value
        # Delegate to the subgenerator
        yield from self.listvalues(node.nextNode)

# Create a LinkedList instance
l = LinkedList()

# Insert values to the list
l.insert(1)
l.insert(3)
l.insert(4)

# Create a generator object to print the 
# contents of the linked list
linkedListValues = l.listvalues(l.head)

# Print using the generator iterator
print("Contents of the linked list:")
for i in linkedListValues:
    print(i)

Output:

Contents of the linked list:

1

3

4

 


Copyright 2023 © pythontic.com