我正在学习递归生成器,并在网上找到了这个程序。
我理解了按顺序遍历的递归版本,但我在理解递归生成器时遇到了麻烦。
具体来说,我无法理解
- 为什么在 for 循环中写了"yield x"?
- 为什么"yield x"没有被收集在最终列表中?
我试图欺骗生成器并添加手表,但我发现递归调用执行多次"yield x",并且没有在最终结果中收集。
class Tree:
def __init__(self, label, left=None, right=None):
self.label = label
self.left = left
self.right = right
def __repr__(self, level=0, indent=" "):
s = level*indent + repr(self.label)
if self.left:
s = s + "\n" + self.left.__repr__(level+1, indent)
if self.right:
s = s + "\n" + self.right.__repr__(level+1, indent)
return s
def __iter__(self):
return inorder(self)
def tree(list):
n = len(list)
if n == 0:
return []
i = n // 2
return Tree(list[i], tree(list[:i]), tree(list[i + 1:]))
# Recursive Generator
def inorder(t):
if t:
for x in inorder(t.left):
yield x
yield t.label
for x in inorder(t.right):
yield x
收益 x 在 for 循环中的作用。
也许您不了解生成器的工作原理?生成器与迭代器不同,它不是直接计算有价值的集合,而是动态获取所有值。如果inorder(t.left)
的结果没有被for
循环遍历,则yield inorder(t.left)
将返回为t.left
创建的整个生成器。因为你的整个inorder
函数都是一个生成器。
不幸的是,我无法找到具体的描述文档。这是基于我的经验的描述。欢迎其他人对我的意见进行更正。如果有人可以提供具体的官方描述,欢迎补充
不确定您要查找的内容,但也许是以下内容:
class Tree:
def __init__(self, label, left=None, right=None):
self.label = label
self.left = left
self.right = right
def __repr__(self, level=0, indent=" "):
s = level*indent + repr(self.label)
if self.left:
s = s + "n" + self.left.__repr__(level+1, indent)
if self.right:
s = s + "n" + self.right.__repr__(level+1, indent)
return s
def __iter__(self):
return inorder(self)
def tree(list):
n = len(list)
if n == 0:
return []
i = n // 2
return Tree(list[i], tree(list[:i]), tree(list[i + 1:]))
def inorder(t):
if t:
for x in t.left:
yield x
yield t.label
for x in t.right:
yield x
t = tree("ABCDEFG")
[print(i.label) for i in t]
其中输出:
A
B
C
D
E
F
G
使用该代码,您可以改为:
[print('----------n', i) for i in t]
输出树中的每个分层节点,从 A 到 G。
编辑:如果你问生成器是如何工作的,也许这个例子可能会有所启发:
>>> def list2gen(lst):
... for elem in lst:
... yield str(elem) + '_'
...
>>> print(list2gen([1,2,'7',-4]))
<generator object list2gen at 0x000001B0DEF8B0C0>
>>> print(list(list2gen([1,2,'7',-4])))
['1_', '2_', '7_', '-4_']
如果调试器多次中断,但这些元素从未在生成的生成器中具体化,则必须将其归因于调试器中的错误。我已经十多年没有在 Python 中使用过一个了;他们曾经是出了名的虫子出没。在Python中,范式是"测试为王"和"避免手动调试",但我不同意这一点。(我不这样做的唯一原因是缺乏出色的IDE和调试器。