陷入了一种我在没有帮助的情况下努力抓住的行为。这是一个递归函数:
OPERATORS = ['+', '-', '*', '/']
def recursive(value, operands):
if not operands:
return value
for operator in OPERATORS:
new_value = str(eval(value + operator + operands[-1]))
new_operands = operands[:-1]
yield from recursive(new_value, new_operands)
def countdown(value, operands):
return next(i for i in recursive(value, operands) if i == '0')
ans = countdown('5', ['1', '2', '3'])
print(ans)
return value
引发调用者未处理的StopIteration
,因此在返回任何内容之前会引发异常。
如果return value
被yield value; return
替换为:
def recursive(value, operands):
if not operands:
yield value
return
for operator in OPERATORS:
new_value = str(eval(value + operator + operands[-1]))
new_operands = operands[:-1]
yield from recursive(new_value, new_operands)
或yield value; raise StopIteration
或yield value; raise StopIteration(value)
或循环隐藏在else
子句下,然后异常由调用者以我期望的方式处理,函数最终返回'0'
。所有这些都会引发异常:raise StopIteration
,无论是裸的还是带参数的,yield; return value
和裸return
。
简而言之,在StopIteration
被提升且yield
从未返回时,来电者会中断。
为什么?
PEP380声明第一个StopIteration
的处理方式与其他方式不同。 PEP479说:
目前,在生成器函数内意外引发的StopIteration将被解释为循环结构驱动生成器的迭代结束。
显然,除了第一次。但是,我不清楚底层实施的细节和背后的确切推理。
还有两个问题:
编写此代码段的正确方法是什么? return (yield value)
是怪癖,特征还是别的什么?
修改:修复了代码中的错误
Edit2:据我所知,第一个代码段中的执行流程如下:
countdown
从recursive('5', ['1', '2', '3'])
recursive('11', [])
StopIteration('11')
被提出这是棘手的部分。这里发生了什么?如何处理StopIteration
?
第二个片段:
'11'
向上屈服,直至倒计时if '11' == '0'
yield '11'
并提升StopIteration
'0'
从我现在看到的,这是非常期待的行为。 StopIteration
被其调用者拦截,不会向上传播。呼叫者反过来引发StopIteration
而没有参数。这就是原始异常的'11'
部分永远不会达到countdown
的原因。 StopIteration
countdown
recursive('5', ['1', '2', '3']
引发了第一个代码段回溯中的异常InternalXmlHelper.vb
。
答案 0 :(得分:0)
StopIteration
。在此之前,您将继续重复列表,评估结果并缩短列表。我认为收益已经返回,但它返回到调用者,这是之前调用的recursive
,而不是countdown
。
在第二个示例中,您会产生一个值,随后调用recursive
会引发StopIteration
,因为它会立即返回。
至于示例return (yield 42)
,是的,这是一个怪癖。这个问题的海报是制作发电机的绊脚石,并发现他后来认为错误的代码实际上已经归还了一些东西。