使用yield进行递归
有没有办法混合递归和yield语句?例如,一个无限数生成器(使用递归)将类似于:
def infinity(start):
yield start
# recursion here ...
>>> it = infinity(1)
>>> next(it)
1
>>> next(it)
2
我尝试过:
def infinity(start):
yield start
infinity(start + 1)
并且
def infinity(start):
yield start
yield infinity(start + 1)
但是它们都没有达到我想要的效果,第一个生成器在生成 start
后停止,第二个生成器生成 < code>start,然后是生成器,然后停止。
注意:拜托,我知道你可以使用 while 循环来做到这一点:
def infinity(start):
while True:
yield start
start += 1
我只是想知道这是否可以递归地完成。
Is there any way to mix recursion and the yield
statement? For instance, a infinite number generator (using recursion) would be something like:
def infinity(start):
yield start
# recursion here ...
>>> it = infinity(1)
>>> next(it)
1
>>> next(it)
2
I tried:
def infinity(start):
yield start
infinity(start + 1)
and
def infinity(start):
yield start
yield infinity(start + 1)
But none of them did what I want, the first one stopped after it yielded start
and the second one yielded start
, then the generator and then stopped.
NOTE: Please, I know you can do this using a while-loop:
def infinity(start):
while True:
yield start
start += 1
I just want to know if this can be done recursively.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,您可以这样做:
不过,一旦达到最大递归深度,这就会出错。
从 Python 3.3 开始,您将能够使用
If you just recursively call yourgenerator function withoutlooping it or
yield from
-ing it,你所做的就是构建一个新的生成器,而不需要实际运行函数体或产生任何东西。有关更多详细信息,请参阅 PEP 380。
Yes, you can do this:
This will error out once the maximum recursion depth is reached, though.
Starting from Python 3.3, you'll be able to use
If you just call your generator function recursively without looping over it or
yield from
-ing it, all you do is build a new generator, without actually running the function body or yielding anything.See PEP 380 for further details.
在某些情况下,对于生成器来说,最好使用堆栈而不是递归。应该可以使用堆栈和 while 循环重写递归方法。
下面是一个使用回调并且可以使用堆栈逻辑重写的递归方法的示例:
上面的方法遍历节点树,其中每个节点都有一个可能包含子节点的
children
数组。当遇到每个节点时,会发出回调并将当前节点传递给它。该方法可以这样使用,打印出每个节点上的一些属性。
使用堆栈代替,并将遍历方法编写为生成器
(注意,如果您想要与原来相同的遍历顺序,则需要反转子级的顺序,因为附加到堆栈的第一个子级将是最后一个弹出。)
现在您可以获得与上面的
traverse_tree
相同的行为,但使用生成器:这不是一个一刀切的解决方案,但对于某些生成器,您可能会得到一个很好的结果替代递归的堆栈处理。
In some cases it might be preferable to use a stack instead of recursion for generators. It should be possible to rewrite a recursive method using a stack and a while loop.
Here's an example of a recursive method which uses a callback and can be rewritten using stack logic:
The above method traverses a node tree where each node has a
children
array which may contain child nodes. As each node is encountered, the callback is issued and the current node is passed to it.The method could be used this way, printing out some property on each node.
Use a stack instead and write the traversal method as a generator
(Note that if you want the same traversal order as originally, you need to reverse the order of children because the first child appended to the stack will be the last one popped.)
Now you can get the same behavior as
traverse_tree
above, but with a generator:This isn't a one-size-fits-all solution but for some generators you might get a nice result substituting stack processing for recursion.