关于python:将项添加到列表解析中的列表

Appending item to lists within a list comprehension

我有一张单子,比如说,a = [[1,2],[3,4],[5,6]]

我想将字符串'a'添加到列表a中的每个项目中。

当我使用:

1
 a = [x.append('a') for x in a]

返回[None,None,None]

但是如果我使用:

1
a1 = [x.append('a') for x in a]

然后它会做一些奇怪的事情。

a而不是a1[[1,2,'a'],[3,4,'a'],[5,6,'a']]

我不明白为什么第一个调用返回[None, None, None],为什么第二个调用在a上而不是a1


list.append改变列表本身并返回None。列表理解用于存储结果,如果您只想更改原始列表,那么在本例中,这不是您想要的。

1
2
3
4
5
6
>>> x = [[1, 2], [3, 4], [5, 6]]
>>> for sublist in x:
...     sublist.append('a')
...
>>> x
[[1, 2, 'a'], [3, 4, 'a'], [5, 6, 'a']]

正如其他人所说,append使列表本身发生变异,您不应该将其赋给变量。执行它会改变它的数据,有效地更新指向它的每个人。

但是,当我想在改变现有对象(而不是构建新的对象,在本例中是使用a=[x + ['a'] for x in a],或者特别是x + ['a'])的时候,有一个技巧我使用。

所以,如果你足够勇敢,你也可以这样做:

1
2
3
4
>>> a=[[1,2],[3,4],[5,6]]
>>> a=[x.append('a') or x for x in a]
>>> a
[[1, 2, 'a'], [3, 4, 'a'], [5, 6, 'a']]

这是因为append返回Noneor继续寻找一个真y值,x是(它是一个list至少有附加的值)。

为什么我还要这个?

假设您有一个列表,并且希望将它的一些成员插入到新列表中,并相应地更新引用:

所以你有清单all

1
>>> all = [[], [], [], []]

其中一些被插入并更新为新列表x

1
2
3
>>> x = [i.append('x') or i for i in all[:2]]
>>> x
[['x'], ['x']]

一些all也被插入并更新到列表y中:

1
>>> y = [i.append('y') or i for i in all[1:3]]

更新all

1
2
>>> all
[['x'], ['x', 'y'], ['y'], []]

x也更新了:

1
2
>>> x
[['x'], ['x', 'y']]

预计产生y

1
2
>>> y
[['x', 'y'], ['y']]

总的来说,对于简单的任务,我建议显式地使用for循环更新。这就是所谓的Python。

从技术上讲,如果您可以访问List类,则可以将其作为一个函数:

1
2
3
def more_functional_append(self, x):
    self.append(x)
    return self
  • 函数式编程是基于每一个基本上都在做一件事的语句,并且没有副作用(所以,不会发生变化和返回)。append不是很实用,因为它改变了一个列表(纯函数编程只有不变的对象),并且不返回结果传递给其他操作(函数)。使用函数式编程概念,您可以创建无人能读的大型单行程序,也称为"作业安全性"或"坏代码"。


对于第一种情况,返回[None, None, None]的原因是list.append函数返回None,这就是它存储在列表中的原因。

在第二种情况下,这是因为列表是可变的,每次附加值时,原始列表都会被修改。

您需要的是一个非就地附加运算符,如+。即[x + ['a'] for x in a]


(这是Mike Graham和Sykora的答案组合):

如果只想在适当的位置更改值,请尝试使用常规for循环,而不是列表理解:

1
2
for sublist in a:
    sublist.append('a')

如果您想让a单独存在,并将结果放在a1中:

1
a1 = [sublist + ['a'] for sublist in a]

正如他们所解释的,append修改了列表,但没有返回任何值,而+只保留列表,但返回一个新的附加列表。


您可以在列表理解中使用列表添加,例如:

a = [x + ['a'] for x in a]

这为a提供了所需的结果。在这种情况下,可以通过在循环前为变量名分配['a']来提高效率,但这取决于您想做什么。


在理解列表的第一个值分配中,属性错误"nonetype"对象没有属性"append",这有助于解释为什么列表a将加载为无。为了让我的控制台抛出错误,我使用x作为一个变量来理解列表,同时也作为迭代器。

1
2
3
Traceback (most recent call last):
x = [x.append('a') for x in a]
AttributeError: 'NoneType' object has no attribute 'append'

然后,我返回到a for x,它抛出了相同的错误。

1
2
3
Traceback (most recent call last):
a = [x.append('a') for x in a]
AttributeError: 'NoneType' object has no attribute 'append'


保留a =并使用对a的副作用:

1
2
[x.append('a') for x in a]
print a