切片整个列表和直接赋值的切片分配有什么区别?

0xc*_*0de 18 python list variable-assignment slice

我在许多地方看到切片赋值用于lists.当与(非默认)索引一起使用时,我能够理解它的用法,但我无法理解它的用法,如:

a_list[:] = ['foo', 'bar']
Run Code Online (Sandbox Code Playgroud)

这有什么不同

a_list = ['foo', 'bar']
Run Code Online (Sandbox Code Playgroud)

agf*_*agf 28

a_list = ['foo', 'bar']
Run Code Online (Sandbox Code Playgroud)

list在内存中创建一个新的并将名称指向a_list它.这与a_list之前指出的无关.

a_list[:] = ['foo', 'bar']
Run Code Online (Sandbox Code Playgroud)

使用a 作为索引调用对象的__setitem__方法,并在内存中创建new 作为值.a_listslicelist

__setitem__评估它slice以确定它代表什么索引,并调用iter它传递的值.然后迭代对象,将每个索引设置在由对象指定的范围内slice的下一个值.对于lists,如果由指定的范围slice与可迭代的长度不同,list则调整大小.这允许您执行许多有趣的操作,例如删除列表的部分:

a_list[:] = [] # deletes all the items in the list, equivalent to 'del a_list[:]'
Run Code Online (Sandbox Code Playgroud)

或在列表中间插入新值:

a_list[1:1] = [1, 2, 3] # inserts the new values at index 1 in the list
Run Code Online (Sandbox Code Playgroud)

但是,对于"扩展切片",其中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
Run Code Online (Sandbox Code Playgroud)

切片分配的主要内容a_list是:

  1. a_list 必须已经指向一个对象
  2. 修改该对象,而不是指向a_list新对象
  3. 这个对象必须支持__setitem__slice指数
  4. 右侧的对象必须支持迭代
  5. 没有名称指向右侧的对象.如果没有其他引用(例如,当它是您的示例中的文字时),则在迭代完成后,它将被引用计数不存在.


Joc*_*zel 12

差异是巨大的!在

a_list[:] = ['foo', 'bar']
Run Code Online (Sandbox Code Playgroud)

您修改绑定到该名称的现有列表a_list.另一方面,

a_list = ['foo', 'bar']
Run Code Online (Sandbox Code Playgroud)

为名称指定一个新列表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
Run Code Online (Sandbox Code Playgroud)