问题描述
我以为我了解Python切片操作,但是当我尝试更新切片列表时,我感到困惑:
I thought I understood Python slicing operations, but when I tried to update a sliced list, I got confused:
>>> foo = [1, 2, 3, 4]
>>> foo[:1] = ['one'] # OK, foo updated
>>> foo
['one', 2, 3, 4]
>>> foo[:][1] = 'two' # why foo not updated?
>>> foo
['one', 2, 3, 4]
>>> foo[:][2:] = ['three', 'four'] # Again, foo not updated
>>> foo
['one', 2, 3, 4]
为什么foo[:][1] = 'two'
之后不更新foo?
Why isn't foo updated after foo[:][1] = 'two'
?
更新:也许我没有清楚地解释我的问题.我知道切片时会创建一个新列表.我的疑问是为什么切片任务会更新列表(例如foo[:1] = ['one']
),但是如果切片有两个级别,它就不会更新原始列表(例如foo[:][2:] = ['three', 'four']
).
Update: Maybe I didn't explain my questions clearly. I know when slicing, a new list is created. My doubt is why a slicing assignment updates the list (e.g. foo[:1] = ['one']
), but if there are two levels of slicing, it doesn't update the original list (e.g. foo[:][2:] = ['three', 'four']
).
推荐答案
这是因为python 不具有可以分配的 l 值.相反,某些表达式具有不同的赋值形式.
This is because python does not have l-values that could be assigned. Instead, some expressions have an assignment form, which is different.
A foo[something]
是用于以下方面的语法糖:
A foo[something]
is a syntactic sugar for:
foo.__getitem__(something)
,但是foo[something] = bar
是一种语法糖,因为它与众不同:
but a foo[something] = bar
is a syntactic sugar for rather different:
foo.__setitem__(something, bar)
切片只是something
的特例,因此foo[x:y]
扩展为
Where a slice is just a special case of something
, so that foo[x:y]
expands to
foo.__getitem__(slice(x, y, None))
和foo[x:y] = bar
扩展为
foo.__setitem__(slice(x, y, None), bar)
现在带有切片的__getitem__
返回一个新列表,该列表是指定范围的副本,因此对其进行修改不会影响原始数组.借助__setitem__
是另一种方法来分配作品,可以简单地完成其他事情.
Now a __getitem__
with slice returns a new list that is a copy of the specified range, so modifying it does not affect the original array. And assigning works by the virtue of __setitem__
being a different method, that can simply do something else.
但是,特殊分配处理仅适用于最外部的操作.成分是正则表达式.所以当你写
However the special assignment treatment applies only to the outermost operation. The constituents are normal expressions. So when you write
foo[:][1] = 'two'
它扩展到
foo.__getitem__(slice(None, None, None)).__setitem__(1, 'two')
foo.__getitem__(slice(None, None, None))
部分创建一个副本,并且该副本被__setitem__
修改.但不是原始数组.
the foo.__getitem__(slice(None, None, None))
part creates a copy and that copy is modified by the __setitem__
. But not the original array.
这篇关于更新切片列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!