118

Python 文档说切片列表会返回一个新列表。
现在,如果返回“新”列表,我有以下与“分配给切片”相关的问题

a = [1, 2, 3]
a[0:2] = [4, 5]
print a

现在输出将是:

[4, 5, 3] 
  1. 正在返回的东西怎么会出现在表达式的左侧?
  2. 是的,我阅读了文档,它说这是可能的,现在既然切片列表返回一个“新”列表,为什么要修改原始列表?我无法理解其背后的机制。
4

5 回答 5

140

您混淆了两个使用非常相似语法的不同操作:

1)切片:

b = a[0:2]

这会复制 的切片a并将其分配给b

2)切片分配:

a[0:2] = b

这会将的切片替换a为的内容b

尽管语法相似(我想象中的设计!),但这是两种不同的操作。

于 2012-05-16T17:09:24.783 回答
82

当您a在运算符的左侧指定时=,您使用的是 Python 的正常赋值,它将a当前上下文中的名称更改为指向新值。这不会更改a指向的先前值。

通过a[0:2]在运算符的左侧指定=,您是在告诉 Python 您要使用切片赋值。切片赋值是列表的一种特殊语法,您可以在其中插入、删除或替换列表中的内容:

插入

>>> a = [1, 2, 3]
>>> a[0:0] = [-3, -2, -1, 0]
>>> a
[-3, -2, -1, 0, 1, 2, 3]

删除

>>> a
[-3, -2, -1, 0, 1, 2, 3]
>>> a[2:4] = []
>>> a
[-3, -2, 1, 2, 3]

更换

>>> a
[-3, -2, 1, 2, 3]
>>> a[:] = [1, 2, 3]
>>> a
[1, 2, 3]

笔记:

如果目标序列允许,切片的长度可能与指定序列的长度不同,因此会改变目标序列的长度。-来源

切片分配提供了与元组解包类似的功能。例如,a[0:1] = [4, 5]等价于:

# Tuple Unpacking
a[0], a[1] = [4, 5]

通过元组解包,您可以修改非顺序列表:

>>> a
[4, 5, 3]
>>> a[-1], a[0] = [7, 3]
>>> a
[3, 5, 7]

但是,元组解包仅限于替换,因为您不能插入或删除元素。

在所有这些操作之前和之后,a是完全相同的列表。Python 只是提供了很好的语法糖来就地修改列表。

于 2012-05-16T17:12:12.483 回答
32

我之前遇到过同样的问题,它与语言规范有关。根据assignment-statements

  1. 如果赋值的左侧是订阅,Python 将调用__setitem__该对象。a[i] = x相当于a.__setitem__(i, x)

  2. 如果赋值的左边是 slice,Python 也会调用__setitem__,但参数不同: a[1:4]=[1,2,3]等价于 a.__setitem__(slice(1,4,None), [1,2,3])

这就是为什么'='左侧的列表切片表现不同的原因。

于 2016-02-25T16:26:07.157 回答
5

通过在赋值操作的左侧切片,您可以指定要分配给哪些项目。

于 2012-05-16T17:08:30.810 回答
1

当您这样做时,您将(切片)的a[0:2] = [4,5]左侧分配了 ,右侧 的值。=a[0:2]=[4,5]

于 2021-10-10T17:29:47.723 回答