我有一个生成器,从有向无环图(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)
天真的解决方案:
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)
我认为这现在有效。