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
不会反弹,循环完成且没有冲突。
为什么会这样?我越来越糊涂了。
在第一种情况下,我通过列表理解定义 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
不会反弹,循环完成且没有冲突。