【发布时间】:2019-08-27 11:50:52
【问题描述】:
我编写了一个简单的生成器函数,它接受一个可能包含子列表的列表并尝试将列表展平:
所以 [1, [2, 3], 4, [5, [6, 7], 8]] 应该产生 1,2,3,4,5,6,7,8
如果我只是想打印出值(不是生成器),它看起来像这样,这很有效:
# Code A
def flatten_list_of_lists(my_list):
for element in my_list:
if isinstance(element, list):
flatten_list_of_lists(element)
else:
print(element)
my_list = [1, [2, 3], 4, [5, [6, 7], 8]]
flatten_list_of_lists(my_list)
按预期打印出 1,2,3,4,5,6,7,8
但是,当我将代码更改为:
# Code B
def flatten_list_of_lists(my_list):
for element in my_list:
if isinstance(element, list):
flatten_list_of_lists(element)
else:
yield element
for i in flatten_list_of_lists(my_list):
print(i)
这只是将打印切换到产量,程序只打印出 1,4。
我将在下面粘贴实际有效的代码。但我想知道为什么以前的代码不起作用?如果代码 A 正确“打印”出数字,为什么代码 B 不能正确“输出”数字?
似乎我对生成器如何使用递归存在根本性的误解。
这段代码确实有效:
# Code C
def flatten_list_of_lists_v2(my_list):
for element in my_list:
if isinstance(element, list):
for sub_element in flatten_list_of_lists_v2(element):
yield sub_element
else:
yield element
l = []
for element in flatten_list_of_lists_v2(my_list):
print(element)
然后打印出 1,2,3,4,5,6,7,8
只是一点背景,我刚看完这个视频: https://www.youtube.com/watch?v=LelQTPiH3f4
在那里他解释说,当您设计生成器时,只需在您想要输出的地方放置一个打印件,看看您是否得到正确的结果,然后将打印件切换到输出。所以我猜他的建议并不适用于所有情况,我只是想了解原因。
【问题讨论】:
-
在
code A中,将flatten_list_of_lists(element)更改为yield from flatten_list_of_lists(element)和print(element)更改为yield element -
在代码 B 中,
flatten_list_of_lists(element)是一个返回生成器的语句,但没有对该对象执行任何操作,因此代码继续执行,直到到达下一个yield语句。 -
本质上类似于stackoverflow.com/q/31221826/1126841;您忽略了对
flatten_list_of_lists_v2的递归调用的返回值(或者更确切地说,可以从中提取的值)。如果您是返回值而不是打印它们,那么您在第一个版本中也会遇到同样的问题。 -
该视频给出了糟糕的建议。打印一个值与返回或产生一个值非常不同。
-
比较
x = (lambda x: x)(3)和x = print(3)(假设您没有使用 Python 2 的print语句)。
标签: python recursion generator