Python列表追加行为

Python list append behavior

本问题已经有最佳答案,请猛点这里访问。

真的不知道该如何表述这个问题…

假设我执行以下操作:

1
2
3
4
5
6
    >>> l = [[]]*2
    >>> l
    [[], []]
    >>> l[0].append(1)
    >>> l
    [[1], [1]]

为什么将1附加到两个列表中?


[[]]*2是对同一列表的两个引用的列表。你在附加它,然后看到它两次。


因为实际上只有一个列表。考虑一下:

1
2
3
4
5
6
>>> l = [[]]
>>> l2 = l*2
>>> l2[0] is l[0]
True
>>> l2[1] is l[0]
True

在列表上执行的*2不会复制列表,而是返回一个长度为2的列表,并用相同的引用填充。

你可能想要的是:

1
>>> l = [[] for _ in xrange(2)]

正如@asterisk在注释中提到的那样,所有公共集合都会公开相同的行为。因此,根据经验法则,最好只对具有值语义的不可变类型使用乘法。


显示与内存布局的差异:

1
2
listOfLists = [[]] * 3
listOfListsRange = [[] for i in range(0, 3)]

enter image description here


以下是初始化列表的方法。行变化最慢。

1
2
3
4
5
6
7
nrows = 3; ncols = 5

l_of_ls = [[0]*ncols for i in range(nrows )]

for rix, r in enumerate(l_of_ls):
    for cix, c in enumerate(r):
        print rix, cix, 'val = ',c

结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0 0 val =  0
0 1 val =  0
0 2 val =  0
0 3 val =  0
0 4 val =  0
1 0 val =  0
1 1 val =  0
1 2 val =  0
1 3 val =  0
1 4 val =  0
2 0 val =  0
2 1 val =  0
2 2 val =  0
2 3 val =  0
2 4 val =  0

出于索引的目的也值得注意

1
2
3
4
for rix in range(nrows):
    for cix in range(ncols):
        print l_of_ls[rix][cix],
    print

结果

1
2
3
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0