我在很多地方都看到了list
的切片分配的使用。我可以理解它与(非默认)索引一起使用时的用法,但我无法理解它的用法如下:
a_list[:] = ['foo', 'bar']
与
有什么不同a_list = ['foo', 'bar']
答案 0 :(得分:26)
a_list = ['foo', 'bar']
在内存中创建一个新的list
,并将名称a_list
指向它。与a_list
之前指出的内容无关。
a_list[:] = ['foo', 'bar']
使用__setitem__
作为索引调用a_list
对象的slice
方法,并在内存中创建新的list
作为值。
__setitem__
评估slice
以确定它代表的索引,并对传递的值调用iter
。然后迭代对象,将每个索引设置在slice
指定的范围内,并将其设置为对象的下一个值。对于list
s,如果slice
指定的范围与可迭代的长度不同,则调整list
的大小。这允许你做一些有趣的事情,比如删除列表中的部分:
a_list[:] = [] # deletes all the items in the list, equivalent to 'del a_list[:]'
或在列表中间插入新值:
a_list[1:1] = [1, 2, 3] # inserts the new values at index 1 in the list
但是,对于“扩展切片”,step
不是一个,迭代必须是正确的长度:
>>> lst = [1, 2, 3]
>>> lst[::2] = []
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
ValueError: attempt to assign sequence of size 0 to extended slice of size 2
关于a_list
切片分配的主要内容是:
a_list
必须已指向对象a_list
指向新对象__setitem__
索引slice
答案 1 :(得分:12)
差别很大!在
a_list[:] = ['foo', 'bar']
您修改绑定到名称a_list
的现有列表。另一方面,
a_list = ['foo', 'bar']
为名称a_list
分配新列表。
也许这会有所帮助:
a = a_list = ['foo', 'bar'] # another name for the same list
a_list = ['x', 'y'] # reassigns the name a_list
print a # still the original list
a = a_list = ['foo', 'bar']
a_list[:] = ['x', 'y'] # changes the existing list bound to a
print a # a changed too since you changed the object
答案 2 :(得分:2)
通过分配给a_list
,a_list
仍引用同一个列表对象,并修改内容。通过分配给a_list
,id
现在引用一个新的列表对象。
查看其>>> a_list = []
>>> id(a_list)
32092040
>>> a_list[:] = ['foo', 'bar']
>>> id(a_list)
32092040
>>> a_list = ['foo', 'bar']
>>> id(a_list)
35465096
:
id
正如您所看到的,def foo(a_list):
a_list[:] = ['foo', 'bar']
a = ['original']
foo(a)
print(a)
使用切片分配版本进行了更改。
两者之间的差异可能导致完全不同的结果,例如,当列表是函数的参数时:
a
有了这个,a_list = ['foo', 'bar']
也会被修改,但如果使用a
,viewDidLayoutSubviews
仍然是原始值。
答案 3 :(得分:0)
a_list = ['foo', 'bar']
a=a_list[:] # by this you get an exact copy of a_list
print(a)
a=[1,2,3] # even if you modify a it will not affect a_list
print(a)
print(a_list)