【问题标题】:list comprehension vs iterable. Python newbie列表理解与可迭代。蟒蛇新手
【发布时间】:2016-03-03 14:34:27
【问题描述】:

假设我有一个数组:

array=[1,0,2,3,4,0,0,5,6,0]

我想要一个只返回数字而不是零的列表。所以我做了这个并且它有效:

print(list(y for y in array if y!=0)

我尝试了另一种没有列表理解的方法,但它不起作用,有人可以解释为什么吗?

for y in array:
    if y!=0:
        print(list(y))

还有什么方法可以打印不带 0 的数字列表?

编辑:我尝试使用 for 循环来解决这个问题,如果我在顶部创建一个空列表,它就可以工作。它有效,但我不明白为什么!但是为什么这个有效而另一个无效呢?就速度/内存而言,这个或列表理解哪个更有效?

array=[1,0,2,3,4,0,0,5,6,0]
list=[]
for y in array:
    if y!=0:
        list.append(y)
print(list)

【问题讨论】:

  • 您能解释一下为什么您认为第二个版本与第一个相同吗?
  • filter(lambda el: el != 0, array)(但是,请使用[el for el in array if el != 0]
  • @RickTeachey 呃。好吧,在第一个版本中,我看到了“for y in array”,这就是我开始第二个版本的方式。然后回到第一个版本,我看到 'if y!=0' 所以我在第二个版本中写了这个。然后他们两个都打印出 y!我确实注意到,在第一个版本中,所有内容都转换为列表,而第二个版本,我尝试仅将 y 转换为列表。但我还是不明白发生了什么
  • temp = (y for y in array if y!=0) 是类型生成器。 list(temp) 将返回一个列表。但 list(0) 会报错,见这里stackoverflow.com/questions/19523563/…
  • @RickTeachey 在第二个版本中:如果我只是打印(y),我会得到一个没有零的所有数字的迭代,这很好。我只是尝试通过执行 list(y) 将其转换为列表,但它不起作用。

标签: python list-comprehension


【解决方案1】:

让我们好好看看你认为正确的地方:

for y in array:
    if y!=0:
        print(list(y))

所以我们遍历数组中的每个值。如果值不为零,我们打印list(y)。问题从这里开始。因为y 是整数,所以list(y) 会返回错误,因为您无法将整数转换为列表。如果您使用print(y),它会起作用。

但随之而来的是另一个问题。如果我们打印列表中不是零的每个元素,我们会得到这样的结果,因为该代码只会按顺序打印:

1
2
3
4
5
6

您在问题中声明您想要一个列表。所以这段代码也不起作用,因为没有存储列表。所以我们终于得到了正确的答案:

array=[1,0,2,3,4,0,0,5,6,0]
list=[]
for y in array:
    if y!=0:
        list.append(y)
print(list)

此答案将每个不为零的y 值存储在列表中,然后最终打印出列表。

编辑:

这就是列表推导的工作原理:

首先,我不禁注意到您犯了语法错误。 :P 你忘了结尾括号!这是正确的代码: print(list(y for y in array if y != 0)).

其次,我需要声明那是不是列表理解。那是一个发电机。有细微的差别。

列表推导会在现场生成列表。列表理解如下所示:[y for y in array if y != 0]

生成器,也就是您在上面使用的,是存储的表达式。它看起来像这样:y for y in array if y != 0

所以不用list(y for y in array if y != 0,你可以直接去[y for y in array if y != 0]

所以现在我将解释“列表理解”(生成器表达式)的实际工作原理。它首先循环遍历array 的每个值。它检查该值是否不为零。如果不是,它会将y 添加到输出列表中。所以基本上,生成器表达式与带有 for 循环的第二个工作代码相同,除了 python 为您创建输出列表,增加了一些便利。

【讨论】:

  • 哇,现在我明白了!多谢!你能解释一下第一个版本是如何工作的吗(列表理解)
【解决方案2】:

如果您想使用for 循环来执行此操作,您需要执行以下操作:

nonzero = []
for y in array:
   if y != 0:
      nonzero.append(y)
print(nonzero)

但是列表理解或filter 在可读性和速度方面都会更好。

【讨论】:

    【解决方案3】:

    在您的第二次尝试中,您拥有 list(y),而您应该拥有 y。由于 y 是单个 int 而不是可迭代的,list(y) 失败。这是输出:

    >>> array=[1,0,2,3,4,0,0,5,6,0]
    >>> print(list(y for y in array if y!=0))
    [1, 2, 3, 4, 5, 6]
    >>> for y in array:
        if y!=0:
            print(list(y))
    
    
    Traceback (most recent call last):
      File "<pyshell#49>", line 3, in <module>
        print(list(y))
    TypeError: 'int' object is not iterable
    >>> for y in array:
        if y!=0:
            print(y)
    
    
    1
    2
    3
    4
    5
    6
    

    另一种方法是使用filter,像这样:

    >>> print(list(filter(bool,array)))
    [1, 2, 3, 4, 5, 6]
    

    filter 接受一个函数和可迭代对象,将函数应用于可迭代对象中的每个项目,并仅返回函数返回真值的项目。如果 y 为 0(假),bool 为 False,否则为 True,它非常适合这些目的。不过,看看您也可以这样做可能对您有用:

    >>> print(list(filter(lambda x:x != 0, array)))
    [1, 2, 3, 4, 5, 6]
    

    我知道你也想知道为什么第一个版本有效。

    >>> print(list(y for y in array if y!=0))
    

    这里,for y in array 是一个 generator,一种特殊的 Python 对象,每次你请求它时都会吐出一个值,可以这么说。所以让我这样分解:

    print(                              )    #Print
          list(                        )     #Convert iterable to list
                 for y in array              #For each y in array...
                                if y!=0      #If y is not zero...
               y                             #Include y in the iterable for list()
    

    这有帮助吗?

    【讨论】:

    • 哦,所以 y 是单个 int 因为 for 循环遍历数组中的每个单个数字?所以当我做列表(y)时,它不起作用,因为它基本上是在做列表(单个数字),这不应该起作用?
    • print (filter(lambda x:x != 0, array)) 应该没问题。
    • @ChengchengPei:不,它会打印出类似&lt;filter object at 0x00000000032BFBA8&gt;的东西。
    • @Angular:查看我的编辑以了解列表理解版本的说明。
    • @ChengchengPei:这里是 Python 3.3。
    【解决方案4】:

    当您创建for 循环时,该循环中的所有内容(所有内容)都会在每次循环中执行一次。所以这一行:

    print(list(y)) 
    

    ...每次循环都打印一个新的list。而在第一个版本中:

    print(list(y for y in array if y!=0)) 
    

    ...只打印了一件事:list() 理解的结果。

    编辑:如果你想修复第二个版本中的'int' object is not iterable错误,你可以这样做:

    for y in array:
        if y!=0:
            print([y])
    

    list 函数需要一个可迭代对象作为输入。一个整数是不可迭代的,所以我们用括号括起来把它放在list 中,这基本上做同样的事情。使用上面的版本,您会看到每次循环都会创建一个新的list

    【讨论】:

    • 我试过这个,但我得到的输出是这样的:[[1],[2],[3],[4],[5],[6]] 所以它把每个数字进入它自己的列表=(
    • 这是它应该做的。再次阅读我的答案:print([y])每次循环都运行。因此,您每次都会得到一个新列表,其中包含一个数字(例如,[1][2] 等)。
    • 是的。由于我们在这个话题上,如果我做类似 [0]*4 的事情,我会得到 [0,0,0,0]。我该怎么做才能得到 [0],[0],[0],[0].
    • @Angular 你打算用 "[0],[0],[0],[0]" 代表什么?你的意思是列表列表吗?如果是这样,您可以这样做:[[0] for x in range(4)].
    【解决方案5】:

    list() 是一个构造函数,它接受零个参数或一个可迭代对象,例如列表、str 或元组。问题是 int 不是可迭代的,其中作为列表推导式 ([y for y in array if y!= 0]) 返回可迭代并可用于创建列表Python documentation

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-03
      • 2022-06-24
      • 1970-01-01
      • 1970-01-01
      • 2017-08-30
      • 1970-01-01
      相关资源
      最近更新 更多