Python 生成器让我困惑

Python generator confusing me

为什么会这样?我越来越糊涂了。 在第一种情况下,我通过列表理解定义 chunked_test_list 。输出符合预期。 但是,在下一种情况下,我将 chunked_test_list 定义为生成器。然后,当我用 for 循环查看它时,只有第一个循环给了我预期的结果,其余的是 EMPTY 列表。我很困惑.. 而且,在最后一种情况下,我在 for 循环中将变量名从 test_list 更改为 test_list_1,然后结果如预期的那样 运行。哦,我更糊涂了

test_list = [1, 2, 3, 4, 5, 6, 7, 8]
step = 2

chunked_test_list = [test_list[x: x + step] for x in range(0, len(test_list), step)]
for test_list in chunked_test_list:
    print('test_list', test_list)

# >>>output
# test_list [1, 2]
# test_list [3, 4]
# test_list [5, 6]
# test_list [7, 8]
test_list = [1, 2, 3, 4, 5, 6, 7, 8]
step = 2

chunked_test_list = (test_list[x: x + step] for x in range(0, len(test_list), step))  # GENERATOR
for test_list in chunked_test_list:  # the variable name `test_list` is SAME to list above
    print('test_list', test_list)

# >>>output
# test_list [1, 2]
# test_list []
# test_list []
# test_list []
test_list = [1, 2, 3, 4, 5, 6, 7, 8]
step = 2

chunked_test_list = (test_list[x: x + step] for x in range(0, len(test_list), step))  # GENERATOR
for test_list_1 in chunked_test_list:  # the variable name `test_list` is NOT same to list above
    print('test_list_1', test_list_1)

# >>>output
# test_list_1 [1, 2]
# test_list_1 [3, 4]
# test_list_1 [5, 6]
# test_list_1 [7, 8]

您看到的结果正式是由生成器中的名称绑定引起的,如 PEP289 中所述。

列表理解chunked_test_list = [test_list[x: x + step] for x in range(0, len(test_list), step)] 引用test_list,但会立即创建一个切片列表列表。将名称 test_list 重新绑定为后续循环变量不会影响列表的元素 chunked_test_list.

现在让我们来看看生成器

chunked_test_list = (test_list[x: x + step] for x in range(0, len(test_list), step))

循环表达式 range(0, len(test_list), step) 立即被评估。该行一运行就创建了范围,您可以看到它使用预期的 len(test_list) 迭代次数。

同时,每次外部 for 循环调用 next 时都会计算生成器循环的主体 test_list[x: x + step]。循环 for test_list in chunked_test_list: 在每次迭代中有效地执行赋值 test_list = gen.next()。在第一次调用 next 期间,test_list 被绑定到它的原始值。您会按预期看到生成器打印的第一个元素。但是,一旦调用 returns,名称 test_list 就会绑定到 next 的结果。由于 return 值中的 none 足够长以支持范围生成的索引,因此您会看到空列表。

当您将生成器中的循环变量重命名为 test_list_1 时,test_list 不会反弹,循环完成且没有冲突。