list [:]和list:如果我要更改列表,请使用哪一个?

时间:2018-03-17 02:01:24

标签: python list edit-in-place

我想从第k个元素IN PLACE中反转一个列表,这是我的代码:

list[:] = list[len(list) - k:] + list[:len(list) - k]

我知道这是正确的代码,而以下代码不正确。谁知道为什么?

list = list[len(list) - k:] + list[:len(list) - k]

谢谢!

1 个答案:

答案 0 :(得分:1)

区别在于python language reference中指定的赋值语法的反映。您的第一个示例生成列表的修改副本,并将列表的内容设置为副本的内容。第二个示例生成修改后的副本,并指定list标识符指向该副本。

您可以通过在列表中之前和之后调用id来更清楚地看到这一点:

id(list)
list[:] = list[len(list) - k:] + list[:len(list) - k]
id(list)  # prints the same id as above

id(list)
list = list[len(list) - k:] + list[:len(list) - k]
id(list)  # prints a new id representing a new list object

在第二种情况下,list具有不同的ID,因为它实际上代表一个新的列表对象,其中第一个重用list并且仅更新内容。

话虽如此,但请注意,在这两种情况下都会制作一份清单副本,因此您并没有真正获得任何收益。这些更新都不是真正的就地计算。出于这个原因,在99%的情况下,我会使用第二个更简洁的语法。

此外,“就地”版本涉及更新列表中可能的许多元素,其中只更新list标识符始终是单个更新。通过以下实验,您可以看到额外复制工作带来的小型性能开销:

$ python -m timeit 'x=range(100000); x[:]=x[::-1]'
100 loops, best of 3: 3.62 msec per loop
$ python -m timeit 'x=range(100000); x=x[::-1]'
100 loops, best of 3: 2.62 msec per loop

$ python -m timeit 'x=range(10); x[:]=x[5:] + x[:5]'
1000000 loops, best of 3: 1.31 usec per loop
$ python -m timeit 'x=range(10); x=x[5:] + x[:5]'
1000000 loops, best of 3: 1.02 usec per loop