在Python中从块内停止生成器

Mat*_*ieu 4 python generator

我有一个生成器,从有向无环图(DAG)生成节点,深度优先:

def depth_first_search(self):
    yield self, 0 # root
    for child in self.get_child_nodes():
        for node, depth in child.depth_first_search():
            yield node, depth+1
Run Code Online (Sandbox Code Playgroud)

我可以像这样遍历节点

for node, depth in graph.depth_first_search():
    # do something
Run Code Online (Sandbox Code Playgroud)

如果满足某些条件,我希望能够从for循环告诉生成器停止在图中更深入.

我提出了以下解决方案,它使用外部函数.

def depth_first_search(self, stop_crit=lambda n,d: False):
    yield self, 0 # root
    for child in self.get_child_nodes():
        for node, depth in child.depth_first_search():
            yield node, depth+1
            if stop_crit(node, depth): break
Run Code Online (Sandbox Code Playgroud)

这个解决方案迫使我在定义stop_crit之前声明我需要的变量,以便可以从中访问它们.

在Ruby中,yield返回块中的最后一个表达式,因此可以方便地用于告诉生成器继续或停止.

在Python中实现此功能的最佳方法是什么?

kxr*_*kxr 13

通常在Python中你只会停止使用生成器而忘记它.点.(因此以通常的方式将东西留给垃圾收集器)

然而,通过使用,generator.close()您可以强制立即执行发生器清理,从而立即触发所有终结.

例:

>>> def gen():
...     try: 
...         for i in range(10):
...             yield i
...     finally:
...         print "gen cleanup"
...         
>>> g = gen()
>>> next(g)
0
>>> for x in g:
...     print x
...     if x > 3:
...         g.close()
...         break
...        
1
2
3
4
gen cleanup
>>> g = gen()
>>> h = g
>>> next(g)
0
>>> del g
>>> del h   # last reference to generator code frame gets lost
gen cleanup
Run Code Online (Sandbox Code Playgroud)


Dav*_*d X 6

天真的解决方案:

def depth_first_search(self):
    yield self, 0 # root
    for child in self.get_child_nodes():
        for node, depth in child.depth_first_search():
            if(yield node, depth+1):
                yield None # for .send
                return
Run Code Online (Sandbox Code Playgroud)

您仍然可以正常调用它,但是您必须保存可迭代才能中止:

it = graph.depth_first_search()
for node, depth in it: #this is why there should be pronouns for loop iterables
    stuff(node,depth)
    if quit: it.send(1) 
    # it.next() should raise StopIteration on the next for iteration
Run Code Online (Sandbox Code Playgroud)

我认为这现在有效。