Python中list和list[:]有什么区别?

74

在Python中,listlist[:]有什么区别(如果有的话)?

7个回答

101

阅读时,list是对原始列表的引用,list[:]则是浅复制该列表。

在赋值时,list会重新绑定名称,而list[:]则是替换列表中先前存在的元素。

此外,不要使用list作为变量名,因为它会遮蔽内置函数。


赋值时哪个更快?list 还是 list[:]? - Owais Akbani

32

后者是指对列表的副本的引用,而不是对列表本身的引用。因此,这非常有用。

>>> li = [1,2,3]
>>> li2 = li
>>> li3 = li[:]
>>> li2[0] = 0
>>> li
[0, 2, 3]
>>> li3
[1, 2, 3]

但是这对于np.array不起作用... - CyTex

6
  • 创建一个列表的副本。但它不会引用相同的列表对象。因此,通过更改li[:]创建的副本来更改原始列表的风险是不存在的。
  • 例如:
  • >>> list1 = [1,2,3]
    >>> list2 = list1
    >>> list3 = list1[:]
    >>> list1[0] = 4
    >>> list2
    [4, 2, 3]
    >>> list3
    [1, 2, 3]
    

    这里通过改变list1来改变list2,但是list3没有发生变化。


    5

    另一个有用的示例是在将不同类型赋给列表和列表 [:] 时。例如,

    l = [1,2,3]
    a = numpy.array([4,5,6])
    l = a
    print(l)
    

    结果是一个numpy数组:
    array([4, 5, 6])
    

    当,

    l = [1,2,3]
    a = numpy.array([4,5,6])
    l[:] = a
    print(l)
    

    结果是一个列表:

    [4, 5, 6]
    

    4

    将第一个list应用于变量将创建对原始列表的引用。第二个list[i]将创建一个浅拷贝。

    例如:

    foo = [1,2,3]
    bar = foo
    foo[0] = 4
    

    现在,bar和foo将会是:

    [4,2,3]
    

    但是:

    foo = [1,2,3]
    bar = foo[:]
    foo[0] = 4
    

    结果将会是:

    bar == [1,2,3]
    foo == [4,2,3]
    
    : 是切片的意思。

    4

    然而,如果列表元素本身也是列表,即使 list1 = list[:] 也存在问题。例如:

    >>> a = [[1,2,3],[4,5,6],[7,8,9]]
    >>> b = a[:]
    >>> b[0].remove(2)
    >>> b 
    [[1, 3], [4, 5, 6], [7, 8, 9]]
    >>> a
    [[1, 3], [4, 5, 6], [7, 8, 9]]
    

    这是因为每个复制到b的列表元素本身就是一个列表,而这种列表的复制涉及到与普通的list1 = list2相同的问题。 我发现最简单的方法是显式地按照以下方式复制每个列表元素:

    >>> a = [[1,2,3],[4,5,6],[7,8,9]]
    >>> b=[[j for j in i] for i in a]   
    >>> b
    [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    >>> b[0].remove(2)
    >>> b
    [[1, 3], [4, 5, 6], [7, 8, 9]]
    >>> a
    [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
    

    当然,对于嵌套列表中每增加一个层级,复制代码就会通过额外的内联for循环进一步加深。


    1
    如果您的外部列表具有不同或未知级别的嵌套(i可能无法迭代),则会遇到严重问题。如果您有嵌套列表,则应使用copy模块,而不是嵌套for循环,使用b = copy.deepcopy(a) - RoundTower

    3

    第一个引用指向原始列表。第二个引用指向原始列表的副本。
    看一下这个!

    >>> a = [1, 2, 3]
    >>> b = a
    >>> c = a[:]
    >>> a == b
    True
    >>> a is b
    True
    >>> a == c
    True
    >>> a is c
    False
    >>> a.__repr__
    <method-wrapper '__repr__' of list object at 0x7f87a9ba3688>
    >>> a.__repr__()
    '[1, 2, 3]'
    >>> b.__repr__
    <method-wrapper '__repr__' of list object at 0x7f87a9ba3688>
    >>> c.__repr__
    <method-wrapper '__repr__' of list object at 0x7f87ad352988>
    

    请注意,变量ab都指向地址0x7f87a9ba3688,而变量c则指向0x7f87ad352988
    这种差异非常明显。
    变量ab都引用原始列表对象。
    而变量c指向的是原始列表的副本,因此它位于不同的位置。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接