Python 为什么这个生成器(使用递归)不能产生直观的结果

Python 为什么这个生成器(使用递归)不能产生直观的结果,python,recursion,generator,Python,Recursion,Generator,我编写了一个简单的生成器函数,它接受一个可能包含子列表的列表,并尝试将列表展平: 所以[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_lis

我编写了一个简单的生成器函数,它接受一个可能包含子列表的列表,并尝试将列表展平:

所以[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

只是一点背景,我刚看完这段视频:

在那里,他解释说,当你设计发电机时,只需在你想要产量的地方打印,看看是否得到正确的结果,然后将打印切换到产量。所以我想他的建议并不适用于所有情况,我只是想了解原因。

一个简单的错误-

def flatten_list_of_lists(my_list):
    for element in my_list:
        if isinstance(element, list):
            # add yield from
            yield from flatten_list_of_lists(element)
        else:
            # yield, not print
            yield element

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

for e in flatten_list_of_lists(my_list):
  print(e)
输出

1
2
3
4
5
6
7
8

在代码A中,将listselement的flatte_list_更改为yield,从listselement和printelement的flatte_list_更改为yield。在代码B中,listselement的flatte_list_是一个返回生成器的语句,但没有对该对象执行任何操作,因此代码将继续,直到到达下一个yield语句;您忽略了返回值,或者更确切地说,是可以从递归调用中提取的值,以展平\u list\u of \u v2。如果返回值而不是打印值,那么在第一个版本中也会遇到同样的问题。视频给出了糟糕的建议。打印一个值与返回或生成一个值非常不同。将x=lambda x:x3与x=print3进行比较,假设您没有使用Python 2的print语句。但是为什么我的代码不起作用呢?我用一个子列表调用\u列表的展平\u列表,这样对该列表的调用也会生成该子列表中的值,因为展平\u列表\u从\u列表返回一个生成器,而您没有使用它!这就像说1+1,但不将其分配给变量,或打印它。。。它的计算结果为2,但随后消失您的第一个版本工作,因为它没有返回任何内容;它打印值。谢谢,我想我现在明白了。基本上,我调用此生成器的循环只返回了“第一个生成器”,而没有在生成器中创建任何未来的生成器。另外,谢谢,直到现在,我还从未听说过“yield from”。如果有人感兴趣的话,上面有一些东西。