将生成器直接分配给字典会引发StopIteration错误。

3
为什么这段代码会抛出 "StopIteration" 异常?
stub_generator = (x for x in range(5))
stub_dict = {}
stub_dict[next(stub_generator)] = list(stub_generator)

这个可以工作吗?
stub_generator = (x for x in range(5))
stub_dict = {}
temp_1 = next(stub_generator)
temp_2 = list(stub_generator)
stub_dict[temp_1] = temp_2
2个回答

3
这种行为是由以下两个原因造成的:
  1. 赋值语句右侧在左侧之前被计算。

  2. 生成器对象只能被迭代一次。


进一步解释一下,当执行以下代码时:

stub_dict[next(stub_generator)] = list(stub_generator)

this part:

list(stub_generator) 

以下内容将在此部分之前进行评估:

stub_dict[next(stub_generator)]

此外,将stub_generator放入list中会导致生成器被完全迭代,并因此耗尽。然后,在之后评估next(stub_generator)时,会引发StopIteration异常,因为stub_generator现在为空。


然而,这段代码是不同的:

temp_1 = next(stub_generator)
temp_2 = list(stub_generator)

它将在执行list(stub_generator)之前执行next(stub_generator)。这意味着,当将stub_generator转换为列表时,它仍将包含一些项目。

1

根据赋值语句的语言参考,

assignment_stmt ::=  (target_list "=")+ (expression_list | yield_expression)

一个赋值语句会先计算表达式列表(请记住,这可以是单个表达式或逗号分隔的列表,后者会产生元组),然后从左到右将单个结果对象分配给每个目标列表。
因此,右侧的表达式首先被评估。所以,首先执行list(stub_generator),这会用尽生成器,然后您正在执行next(stub_generator),它试图迭代一个已经用尽的生成器。这就是为什么会引发StopIteration的原因。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接