【问题标题】:List comprehensions and one line for-loops列表推导和一行 for 循环
【发布时间】:2017-04-19 18:38:41
【问题描述】:

如果你这样做列表理解:

squares = [x**2 for x in range(100000)]

这会占用大量内存,因此您可以使用生成器来做同样的事情:

squares = (x**2 for x in range(100000))

现在假设我想使用单行 for 循环来打印所有这些方块:

[print(square) for square in squares]

我的问题是:以这种方式打印是否会创建一个列表(看起来像是一个列表理解)?如果是这样,该列表是否存储在内存中? (如果是这样,那么在创建 squares 时使用生成器是没有意义的,因为无论如何它们都会存储在另一个列表中。)还有一件事:如果你这样做:

[1, 2, 3, 4, 5, 6]

如果不将其分配给任何变量,这些值是否会存储在内存中?

【问题讨论】:

    标签: python list python-3.x memory generator


    【解决方案1】:

    是的,这是创建一个 list 并存储在内存中,您不应该将列表推导用作循环的单行,这不是它们的用途。

    你可以这样做:

    for square in (x**2 for x in range(100000)):
        print(square)
    

    【讨论】:

      【解决方案2】:

      如果不将其分配给名称,列表不会存储在内存中,因为没有引用保存它(最初。内存分配给它,但它是立即释放,因为 (C)Python 可以看到你没有使用它*)。

      除此之外,打印:

      [print(square) for square in squares]
      

      效率极低;您使用列表理解只是为了打印的副作用,一个包含print 函数调用(其返回值)的结果 的列表被填充.

      这意味着你最终会得到一个None 的列表,它被创建只是为了被转储,并没有多大用处。

      您最好使用带有for 循环的生成器,正如@user312016 在他的回答中所建议的那样。生成器将按需生成,不会创建额外的列表。

      *在交互模式下,情况有所不同,因为您将名称 _ 用作最近计算的表达式的名称。在那里,列表存储在内存中,直到下一个表达式覆盖附加到 _ 的值。

      【讨论】:

      • 一个重要的说明,它们仍然会由解释器在内存中创建,然后由于缺少引用而被垃圾收集器销毁。
      • 是的 @user312016 ,这就是为什么我写了 “最初内存将被分配,但它立即被释放,因为 Python 可以看到你没有使用它” :-)。我将 OPs“存储在内存中”的问题解释为询问内存是否真的在语句执行后 持续存在。 (在交互模式下_ 保留它,但这是一个例外)
      • 糟糕,我错过了这部分
      • 我通常会在发布后大量编辑我的答案,并在我脑海中出现时添加内容。
      • @Alex 差不多,是的。 (C)Python 内存是通过对对象的引用来管理的(并且,将其分配给一个名称会增加它的引用计数)。如果一个对象没有任何对它的引用,它就会被垃圾回收。
      猜你喜欢
      • 2021-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-26
      • 2016-11-10
      相关资源
      最近更新 更多