【问题标题】:python basic level generator and list questions [duplicate]python基本级别生成器和列表问题[重复]
【发布时间】:2016-09-13 01:11:42
【问题描述】:
my_nums =(i*i for i in [1,2,3,4,5])
for k in (my_nums):
    print(k)
GG = list(my_nums)

print(GG)

打印出来:

1
4
9
16
25
[]

Process finished with exit code 0

我不明白为什么[] 的值是空的(应该是[1,4,9,16,25])?另外,for-loop 是否将生成器值转换为列表?

【问题讨论】:

    标签: python list generator


    【解决方案1】:

    这样的生成器表达式:

    my_nums = (item for item in [1, 2, 3, 4, 5, 6, 7])
    

    是这样的语法糖:

    def generator(iterable):
        for item in iterable:
            yield item
    
    my_nums = generator([1, 2, 3, 4, 5, 6, 7])
    

    forloop 本身就相当于这样:

    while True:
        try:
            item = next(my_nums)
        except StopIteration:
            break
        else:
            print(item)
    

    因为gg = list(iterable) 类似于:

    gg = []
    for item in my_nums:
        gg.append(item)
    

    问题是第一次循环生成器表达式时,它已经用尽了。如果您尝试再次循环它,它只会引发 StopIteration 并中断循环。

    例如:

    >>> my_nums = (i for i in [1, 2])
    >>> list(my_nums)
    [1, 2]
    >>> list(my_nums)
    []
    >>> next(my_nums)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    StopIteration
    >>>
    

    看看你第二次调用list(my_nums)它是如何返回一个空列表的?这是因为发电机已耗尽。如果您尝试从中获取下一个项目,您可以看到它是如何引发 StopIteration 的。

    【讨论】:

      【解决方案2】:

      生成器是迭代器,但您只能对它们进行一次迭代。这是因为它们不会将所有值都存储在内存中,而是动态生成值。

      my_nums =(i*i for i in [1,2,3,4,5])
      for k in (my_nums):
          print(k)
      

      打印出来:

      1
      4
      9
      16
      25
      

      除了使用 () 而不是 [] 之外,它是一样的。但是,您不能再次执行for k in my_nums,因为生成器只能使用一次:它们计算 1,然后忘记它并计算 4,然后逐个计算 25。

      如果你再次尝试执行迭代,你会得到StopIteration traceback。

      这个thread已经详细讨论过了。

      【讨论】:

        【解决方案3】:

        以下是generator comprehension

        my_nums =(i*i for i in [1,2,3,4,5])
        
        for k in (my_nums):
            print(k)
        

        因此,当您第一次循环并打印值时,生成器会打印它可以生成的每个值。 for 循环通过调用my_nums.next() 并将获得的值分配给k 来工作,然后将其打印出来。当引发StopIteration 异常时,for 循环的迭代将停止。

        而且,当你在 for 循环之后使用 GG = list(my_nums) 时,你会得到一个空列表,因为生成器已经用尽并且它不再生成任何内容。

        如果您想将生成器产生的值存储到 list 中,您可以直接执行以下操作:

        my_nums =(i*i for i in [1,2,3,4,5])
        GG = list(my_nums) # no for loop for printing it already
        

        虽然,我不确定如果按照上述方式进行操作,您是否会获得任何优势。

        【讨论】:

        • 知道了!谢谢前辈!
        【解决方案4】:

        仅仅因为你第一次用完发电机!

        my_nums = (i*i for i in [1,2,3,4,5])
        for k in my_nums:
            print(k)
        
        my_nums = (i*i for i in [1,2,3,4,5])
        print(list(my_nums))
        

        【讨论】:

          【解决方案5】:

          那是因为你在做的时候已经用尽了所有生成的值

          for k in (my_nums): # you already made my_nums generate till the end here
              print(k)
          

          将生成器视为从流中读取。您已经阅读了流,因此当您尝试从已经耗尽的生成器中读取更多信息时,您会得到一个空列表

          【讨论】:

            【解决方案6】:

            当你迭代生成器时,你同时清空它。 因此,只需删除 for k in (my_nums): print(k) 即可获得预期结果。

            同样的事情:

            my_nums =(i*i for i in [1,2,3,4,5])
            a = list(my_nums)
            b = list(my_nums)
            print(a)
            // [1,4,9,16,25]
            print(b)
            // []
            

            【讨论】:

              猜你喜欢
              • 2018-04-20
              • 1970-01-01
              • 2010-12-29
              • 1970-01-01
              • 2013-06-07
              • 1970-01-01
              • 2012-01-11
              • 2021-10-20
              相关资源
              最近更新 更多