空生成器

5 投票
1 回答
769 浏览
提问于 2025-04-18 02:08

在玩树结构的时候,我发现了一个有趣的现象:

def descendants (self):
    return #or "pass" or "42"

显然,这段代码返回的是 None

另一方面:

def descendants (self):
    return
    yield 42

这段代码返回的是一个生成器,但它什么都不输出(其实这是我需要的,特别是对于叶子节点)。

有人能给我解释一下这里发生了什么吗?

难道 yield 42 不是不可达代码吗?(我猜测,判断一个函数是生成器还是“普通”函数是在编译时就决定的,主要看它是否包含一个或多个 yield 语句,不管这些语句是否可达。不过这只是我的猜测。)


背景是这样的:我有树结构,每个节点要么是一个树,要么是一个叶子节点。现在我想生成一个节点的所有后代:

class Leaf (Node):
    @property
    def descendants (self):
        return
        yield 42

class Tree (Node):
    @property
    def descendants (self):
        for child in self.children:
            yield child
            yield from child.descendants

1 个回答

5

我理解的是,在一个函数里面使用的 yield 关键字是在编译时就被识别的。这样一来,这个函数就不再像普通的函数那样工作。当你调用一个包含 yield 关键字的函数时,它会立即返回一个懒惰的生成器对象,这个对象会根据函数的定义按需生成变量。只有当你遍历这个生成器时,函数里的代码才会被执行。

更简洁的解释可以在 这里 找到。

所以当调用 descendants 时,由于函数里面有 yield 关键字,立刻返回了一个生成器对象。不过,因为 descendants 立即 return 了,所以这个生成器并没有产生任何值,但它绝对还是一个生成器。

撰写回答