Reputation: 1006
>>> a = [3, 2]
>>> a[0:1][0] = 1
>>> a
[3, 2]
>>> a[0:1] = [1]
>>> a
[1, 2]
What does a[0:1]
mean?
a
, then a[0:1][0] = 1
should change the value of a
.a
, then a[0:1] = [1]
shouldn't change the value of a
.I think the result of the two is inconsistent with each other. Could you please help me work out the problem?
Upvotes: 12
Views: 2889
Reputation: 32189
The following statement:
>>> a[0:1] = [1]
assigns the list [1]
as a subset of the list a
from 0
to 1
.
By doing a[0:1][0]
you are getting the first element of [3]
which is 3. Then if you try to assign it a value of 1, it simply wont work because 3 cannot be 1. However, if you stick to a[0:1]
, you are getting [3]
, which can be changed to [1]
. Hope that helps
>>> a = [1,2,3,4]
>>> a[1:4]
[2,3,4]
>>> a[1:4] = [6,5,4,3,2]
>>> a
[1,6,5,4,3,2]
Upvotes: -1
Reputation: 91049
Internally, this is a big difference:
>>> a = [3, 2]
>>> a[0:1][0] = 1
is a shorthand for
temp = a[0:1]
temp[0] = 1
and is internally expressed as
a.__getitem__(slice(0, 1)).__setitem__(0, 1)
resp.
temp = a.__getitem__(slice(0, 1))
temp.__setitem__(0, 1)
so it accesses a part of the list, making a separate object, and doing an assignment on this object, which is then dropped.
On the other hand,
>>> a[0:1] = [1]
does
a.__setitem__(slice(0, 1), [1])
which just operates on the original object.
So, while looking similar, these expressions are distinct on what they mean.
Let's test that:
class Itemtest(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
def __setitem__(self, item, value):
print "__setitem__", self, item, value
def __getitem__(self, item):
print "__getitem__", self, item
return Itemtest("inner")
a = Itemtest("outer")
a[0:1] = [4]
temp = a[0:1]
temp[0] = 4
a[0:1][0] = 4
outputs
__setitem__ outer slice(0, 1, None) [4]
__getitem__ outer slice(0, 1, None)
__setitem__ inner 0 4
__getitem__ outer slice(0, 1, None)
__setitem__ inner 0 4
Upvotes: 10
Reputation: 20361
Slicing a list creates a shallow copy- it is not a reference to the original. So when you get that slice, it is not bound to the original list
a
. Therefore, you can try and change a single element of it, but it is not stored in a variable so no changes will be made to any original list
.
To clarify, with the former to you doing __getitem__
- accessing part of the list (a copy):
a[0:1][0] = 1
You are editing the slice [0:1]
, which is a only shallow copy of a
, so will not edit a
itself.
But with the latter, one is calling __setitem__
, which will of course edit the object in-place.:
a[0:1] = [1]
You are directly referring to and editing part of a
, so it changes in real-time.
Upvotes: 9