对整个列表进行切片赋值和直接赋值有什么区别?
- 2025-02-08 08:52:00
- admin 原创
- 39
问题描述:
我在很多地方都看到对 s 进行切片赋值的使用list
。我能够理解它在与(非默认)索引一起使用时的用法,但我无法理解它的用法,例如:
a_list[:] = ['foo', 'bar']
这与
a_list = ['foo', 'bar']
?
解决方案 1:
a_list = ['foo', 'bar']
在内存中创建一个新的list
并将名称指向它。之前指向a_list
什么并不重要。a_list
a_list[:] = ['foo', 'bar']
调用以a为索引,以内存中新建的a为值的对象__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
不是 1,则可迭代对象必须具有正确的长度:
>>> 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
右边的对象必须支持迭代
右侧的对象没有指向任何名称。如果没有其他引用它(例如,当它是文字时,如您的示例中所示),则在迭代完成后,它将被引用计数为不存在。
解决方案 2:
差别相当大!
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
解决方案 3:
通过赋值给a_list[:]
,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
则保持其原始值。
解决方案 4:
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)