yield如何在使用递归生成器的Inorder遍历中工作



我正在学习递归生成器,并在网上找到了这个程序。

我理解了

按顺序遍历的递归版本,但我在理解递归生成器时遇到了麻烦。

具体来说,我无法理解

  1. 为什么在 for 循环中写了"yield x"?
  2. 为什么"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和调试器。

最新更新