我试图弄清楚如何将此代码的运行绘制到递归树上,因为即使在调试时,我也不确定它的运行方式。
每个产量在做什么,为什么我都需要它们?

香港专业教育学院试图创建一个树,将每个运行与它的下一个递归连接,但我不知道在yield.data之后的内容,其中头是“ c”

class Node:
    def __init__(self, data, next=None):
        self.data = data
        self.next = next


def get_reverse_iterator(head):
    if head.next:
        for datum in get_reverse_iterator(head.next):
            yield datum
    yield head.data


lst = Node('a', Node('b', Node('c')))
for x in get_reverse_iterator(lst):
    print(x)


结果应该是:
C
b
一种

最佳答案

要了解其工作原理,您需要了解递归的基本概念。假设我们不处理生成器;我们只希望在给定头节点的情况下反向打印列表的所有节点。我们通过将节点作为参数来调用函数print_reverse。如果节点的下一个字段为空,则只打印该字段的数据值。但是,如果next不为空,则它指向必须在打印当前节点之前打印的节点。因此,我们再次递归调用print_reverse以首先打印该节点。当print_reverse返回时,我们现在可以打印当前节点。当然,当我们递归调用print_reverse来打印下一个节点时,它可能会发现还有另一个必须首先打印到的节点,我们将再次递归调用print_reverse。因此,我们有:

class Node:
    def __init__(self, data, next=None):
        self.data = data
        self.next = next


def print_reverse(head):
    if head.next:
        print_reverse(head.next)
    print(head.data)


lst = Node('a', Node('b', Node('c')))
print_reverse(lst)


在理解发电机问题之前,必须先理解以上代码。我们希望创建一个产生该值的生成器函数,而不是创建一个打印节点数据字段的函数print_reverse。因此,重命名函数并用yield语句替换print函数,并用yield from语句递归调用是有意义的:

class Node:
    def __init__(self, data, next=None):
        self.data = data
        self.next = next


def get_reverse_iterator(head):
    if head.next:
        #print_reverse(head.next)
        yield from get_reverse_iterator(head.next)
    #print(head.data)
    yield head.data

lst = Node('a', Node('b', Node('c')))


现在我们可以使用生成器,如下所示:

for x in get_reverse_iterator(lst):
    print(x)


要么:

l = [x in get_reverse_iterator(lst)]


但是使用递归避免创建多个生成器对象的替代方法是:

def get_reverse_iterator(head):
    stack = []
    while head.next:
        stack.append(head)
        head = head.next
    yield head.data
    while len(stack):
        head = stack.pop()
        yield head.data

07-28 01:30
查看更多