python 列表复制:old[:] 和 list(old) 有区别吗?

7 投票
6 回答
506 浏览
提问于 2025-04-17 05:57
old = [1, 2, 3]

这两行代码有什么区别吗?如果有的话,是什么?

new = old[:]
new = list(old)

更新 我之前已经接受了ubershmekel的回答,但后来我了解到一个有趣的事实:对于小列表(10个元素),使用[:]会更快,而对于大列表(100000个元素),使用list()会更快。

~$ python -S -mtimeit -s "a = list(range(10))" "a[:]"
1000000 loops, best of 3: 0.198 usec per loop
~$ python -S -mtimeit -s "a = list(range(10))" "list(a)"
1000000 loops, best of 3: 0.453 usec per loop
~$ python -S -mtimeit -s "a = list(range(100000))" "a[:]"
1000 loops, best of 3: 675 usec per loop
~$ python -S -mtimeit -s "a = list(range(100000))" "list(a)"
1000 loops, best of 3: 664 usec per loop

6 个回答

1

在你给出的例子中,没什么区别:两者都会产生一个全新的 list 对象,里面的元素是一样的。

一般来说:

  • new = old[:] 只适用于支持切片的对象,new 的类型和 old 是一样的。
  • new = list(old) 可以用于任何可迭代的对象,new 会变成一个 list
6

如果 old 不是一个列表,那么 old[:] 会把 old 中的所有元素放在和 old 一样类型的容器里(可能是元组或者字符串),而 list(old) 则会把这些元素放到一个列表里。

举个例子,如果 old 是字符串 'foo',那么 old[:] 还是字符串 'foo',而 list(old) 就变成了列表 ['f', 'o', 'o']。

4

是的,这里有一点小区别。最近在/r/python上有个讨论,讨论的原因是这篇博客提到了一些可读性方面的差异,比如说用[:]的方式在处理生成器时不太适用,而且它会保持和原来一样的类型。

从技术上讲,你得到的结果是一样的——一个全新的列表,但它仍然指向原来的对象。你可以选择你更喜欢的方式(不过[:]稍微快一点)。我个人觉得那篇博客说的list(old)更容易理解。

关于具体的区别,在Python 3.2中:

>>> import dis
>>> def colon(x):
...     return x[:]
...
>>> def new_list(x):
...     return list(x)
...
>>>
>>> dis.dis(colon)
  2           0 LOAD_FAST                0 (x)
              3 LOAD_CONST               0 (None)
              6 LOAD_CONST               0 (None)
              9 BUILD_SLICE              2
             12 BINARY_SUBSCR
             13 RETURN_VALUE
>>> dis.dis(new_list)
  2           0 LOAD_GLOBAL              0 (list)
              3 LOAD_FAST                0 (x)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE
>>>

至于为什么list(old)会慢一点,我认为是因为切片机制不需要在列表构造函数上执行“LOAD_GLOBAL”和“CALL_FUNCTION”,整个操作都是在C语言中处理的。

撰写回答