作业如何使用列表切片?

How does assignment work with list slices?

提问人:Kartik Anand 提问时间:5/17/2012 最后编辑:martineauKartik Anand 更新时间:8/19/2023 访问量:75918

问:

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

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

现在输出为:

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

评论

0赞 Kartik Anand 5/17/2012
@Mark Longair,对不起,我以为只有代码应该格式化,而不是输出
3赞 Josh Lee 5/17/2012
请参见: 6.2 分配语句
0赞 Kartik Anand 5/17/2012
是的,我确实理解作业,但是在切片时生成新列表的概念让我感到紧张
1赞 Casey Kuball 5/17/2012
@KartikAnand 切片分配是一种特殊方案,其中不会创建新列表。创建一个没有名称绑定的对象是没有意义的,因此 python 不会将其作为无效语法丢弃,而是将其转换为更像您可能期望的东西。由于 python 没有引用,因此让切片的结果更改原始列表是行不通的。你会得到一份副本。如果您提供了有关应用程序的更多信息,我们也许能够更好地帮助您以“pythonic”方式做事。:)=
1赞 Kartik Anand 5/17/2012
@Darthfett 我现在没有从事任何应用程序,而是在我开始动手之前自学 python:)

答:

5赞 fraxel 5/17/2012 #1

通过在分配操作的左侧进行切片,可以指定要分配到哪些物料。

156赞 NPE 5/17/2012 #2

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

1)切片:

b = a[0:2]

这将复制 的切片并将其分配给 。ab

2)切片分配:

a[0:2] = b

这会 的切片替换为 的内容。ab

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

评论

8赞 Kartik Anand 5/17/2012
这就是我的疑问,在第二种情况下,为什么不是 a 的切片,一个新列表??
17赞 Marcin 5/17/2012
@KartikAnand 因为事实并非如此。这不是语言所指定的。
0赞 Mark Ransom 5/17/2012
需要明确的是,“取一片”的真正意思是“复制一片”,这就是部分混淆的来源。
4赞 NPE 5/17/2012
@KartikAnand:基本上,是的。口译员知道哪个是哪个,并适当地处理它们。
2赞 Spiros 6/25/2015
@Dubslow:你可以通过使用 itertools 模块来做到这一点。对于您的情况,请使用函数 islice,其中有 , 。这将避免任何副本并使用延迟评估(在您的情况下,延迟访问原始列表)。start=1stop=None
91赞 Casey Kuball 5/17/2012 #3

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

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

插入

>>> 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]

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

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

评论

7赞 Mark Ransom 5/17/2012
相似但不完全相同,因为左侧和右侧的元素数量可能不相等。
0赞 Casey Kuball 5/17/2012
@MarkRansom 这是一个很好的观点,我添加了更多信息来说明这一点。
2赞 jadkik94 5/17/2012
等价于 或 ?a[:] = some_lista = some_list[:]a = some_list
2赞 Casey Kuball 5/17/2012
@jadkik94都不是。 将 的每个元素设置为 的元素。做你提到的任何一个都会改变现状。例如:。如果最后一行更改了 的值,而不是改变它,则最后一行将是 False。a[:] = some_listasome_listaa = [1, 2, 3]b = aa[:] = [4, 5, 6]a is ba
0赞 strikersps 9/20/2020
@CaseyKuball 当我们进行切片分配时,的值应该始终为正吗?start: stop: step
37赞 Stan 2/26/2016 #4

我之前遇到过同样的问题,它与语言规范有关。根据分配声明

  1. 如果赋值的左侧是 subscription,则 Python 将对该对象调用__setitem__。 等效于 。a[i] = xa.__setitem__(i, x)

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

这就是为什么“=”左侧的列表切片的行为不同。

2赞 thing10 10/11/2021 #5

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