这个符号在Python的列表中有什么作用:"someList[:]"?

32

我有时会遇到这种打印或返回列表的方式 - someList[:]。 我不明白为什么人们使用它,因为它返回整个列表。

为什么不直接写someList,不带[:]部分呢?


你是指特定的编程语言吗? - Artur Peniche
5
可能是 如何在 Python 中克隆或复制列表? 的重复问题。 - Łukasz Rogalski
5
可能是解释Python的切片符号的重复问题。 - LittlePanda
12
不是两个问题中的任何一个的重复,尽管两个问题都含有隐含的答案。 - Cephalopod
你可以查看我的问题:http://stackoverflow.com/questions/29884268/how-do-references-in-functions-work。[:] 帮助我解决了我的问题。 - user4638556
6个回答

54

[:] 创建一个切片,通常用于获取列表的一部分。如果没有给出任何最小/最大索引,它将创建整个列表的副本。下面是一个演示的 Python 会话:

>>> a = [1,2,3]
>>> b1 = a
>>> b2 = a[:]
>>> b1.append(50)
>>> b2.append(51)
>>> a
[1, 2, 3, 50]
>>> b1
[1, 2, 3, 50]
>>> b2
[1, 2, 3, 51]

注意如何将值附加到b1还将该值附加到a。然而,向b2附加内容并没有修改a,也就是说b2是一个副本。


谢谢,Frerich,我现在明白了。在那些情况下,我遇到[:]确实是用来复制列表的。 - Petr S
19
值得一提的是,这将创建一个浅拷贝的列表,因此如果你有嵌套的列表,该模式可能会遇到问题。 - sapi
1
从“显式优于隐式”的角度来看,最好是导入“copy”并使用“copy.copy(lst)”而不是切片符号。切片符号没有暗示它的作用,并且很难在谷歌上搜索到相关信息。 - Christian Aichinger

16
在Python中,当你执行a = b时,a并不会取b的值,而是引用b所引用的相同值。要查看这一点,请执行以下操作:
>>> a = {'Test': 42}
>>> b = a
>>> b['Test'] = 24

a的值现在是多少?

>>> a['Test']
24

这与列表类似,所以我们必须找到一种方法来真正复制一个列表,而不是创建对它的引用。一种方法是重新创建列表copy = list(list1),或者使用copy模块的函数。但是,毕竟,最简单、最漂亮、最好的方法(;)就是通过将第一个列表的每个值复制到另一个列表中来实现,例如copy = list1 [:]。它使用切片,这里的list1从索引0到索引len(list1)被切片,因此整个list1被返回!

此外,切片方法略快:使用time.clock()方法测量1000个包含10000个随机整数的列表分配的平均执行时间,使用切片、构造器和深度复制,结果显示切片方法比构造器方法快15%,而深度复制则慢4倍。然而,在使用小列表时,这种时间上的收益是可以忽略的:因此,使用copy = list(list_to_copy)copy = list_to_copy [:]取决于开发人员的喜好。

最后,我们经常忘记列表.copy方法,它似乎更快!实际上,它甚至比切片方法快13%!


1
(对于可变对象而言...)明确地说,如果a是可变的或不可变的,b = a的工作方式完全相同。 - DSM
1
@FrerichRaabe 是的,这是有意主观的,这就是为什么我使用了那么多的最高级形容词和笑脸来强调这一点。 - Spirine
1
答案在我看来是错误的。a = b 不会创建一个对 b 的引用,而是对 b 引用的值的引用。赋值后,两个名称都引用相同的值。实际上,Python 中的每个名称都引用一个值,因此即使在赋值之前复制列表,也会导致引用 - 新列表对象的引用。客观地说,list(L) 在文档中更容易查找,比 L[:] 更灵活,因为 L 可以是任何可迭代的东西,而不仅仅是支持切片的对象。它甚至可以与根本不实现切片的对象一起使用。 - BlackJack
1
自Python 3.3版本开始,list类也拥有了copy方法。 - Veedrac
1
@Veedrac 谢谢,我忘记了这个方法,经过一些测试,它是最快的方式! - Spirine
显示剩余2条评论

8

为了创建一个列表的副本而不是像Python一样传递引用,请使用以下两个示例来理解区别。

示例:

# Passing by reference
SomeListA = [1, 2, 3]
SomeListB = [2, 3, 4]
SomeListB = SomeListA
SomeListA[2] = 5
print SomeListB
print SomeListA

# Using slice
SomeListA = [1, 2, 3]
SomeListB = [2, 3, 4]
SomeListB = SomeListA[:]
SomeListA[2] = 5
print SomeListB
print SomeListA

4

当您需要修改列表时,而又不想更改原列表并创建另一个新列表时,您可以使用

y = [1,2,3]
x = y[:]

你可以对列表进行很多更改,但原始列表将在(y)中,修改后的列表将在(x)中。


-1

#这里有一个更简单的方法,适合初学者理解:

list16 = [1,2,3,4,5,6]
list17 = list16[:] 

#^识别'list17'是'list16'的副本而不是直接引用'list16'

list17[0] = 10

#^ 在新复制的列表中进行更改

print(list17)
print(list16)
= [10,2,3,4,5,6]
= [1,2,3,4,5,6]

#打印列表以便查看发生了什么。我创建了一个列表的副本,并进行了修改,而不改变原始列表。


-2

有2个可用的副本。1)深拷贝 2)浅拷贝。
1)深拷贝是你只复制值
list = ['abc',123,'xyz']
list1 = copy.deepcopy(list) 或 list1 = list[:]

2)浅拷贝是你只引用变量
list2 = copy.copy(list) 或 list2 = list

当您在list2上修改某些内容时,它也会影响到list,因为它是引用。 list1.append(456)
list2.append('789')
print "list: %s" %list
print "list1: %s" %list1
print "list2: %s" %list2
答案:
list : ['abc',123,'xyz','789']
list1 : ['abc',123,'xyz',456]
list2 : ['abc',123,'xyz','789']


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