python - 试图理解生成器的递归运行
问题描述
我试图弄清楚如何将此代码的运行绘制到递归树上,因为我不太确定它是如何运行的,即使我正在调试。每个产量在做什么,为什么我需要它们?
我尝试创建一个有点树,将每个运行递归地连接到下一个运行,但我不知道 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 a
解决方案
要了解它是如何工作的,您需要了解递归的基本概念。假设我们不是在处理生成器;我们只想在给定头节点的情况下反向打印列表的所有节点。我们调用函数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 ,而是希望创建一个生成该值的生成器函数。因此,重命名函数并将 print 函数替换为语句并将递归调用替换为语句是有意义的:yield
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
推荐阅读
- laravel - Docker-组合丢失的文件
- python - 带有多个打开它的按钮的破折号模式
- java - 为什么这条线被java忽略了?
- autoit - 为什么函数“if ProcessExist”在其他计算机中不起作用
- python - 如何将 CP1252 字符串转换为 numpy 中的字符列表
- python-3.6 - 如何将预定义的变量值传递到 Python 中预定义的硬编码字符串的一部分?
- loops - Jmeter - 如何循环请求?
- node.js - 无法从 config.xml 恢复插件“NetworkStatus”。您可能需要再次尝试添加它。错误:错误:npm:命令失败,退出代码为 1
- ansible - 获取归档模块运行的所有一级文件夹
- reactjs - React - TypeError:无法读取未定义的属性“包含”