Public Group

# [Python] Slice notation and object copies

This topic is 3775 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I've decided to try and learn Python. I'm using the tutorial in the documentation and there's something I don't quite understand. When using slice notation, it looks like I am sometimes getting a copy of the object and other times I get the object itself. Sounds vague, I know, but the following example shows what I mean. If I write the following in the python shell:
a = [1, 2, 3]
a[:] = [4, 5, 6]
a
the output is: [4, 5, 6], so the object 'a' was modified, but if I write the following:
a[:].append(7)
a
the output is: [4, 5, 6], so 'a' was not modified, which I assume is because append() was called on a copy of 'a' returned by the [:]. So what's going on? Another question: Why does Python allow me to write the second code snippet? I mean, modifying a temporary copy of 'a' doesn't make sense, so shouldn't this be flagged as an error (like it does in C++)? Thanks in advance.

##### Share on other sites
Quote:
 Original post by Gage64modifying a temporary copy of 'a' doesn't make sense, so shouldn't this be flagged as an error (like it does in C++)?

Modifying temporary copies is completely legal in C++:
std::vector<int> a;a.push_back(1);std::vector<int>(a).push_back(2); // !!!

##### Share on other sites
Quote:
 Original post by bubu LVModifying temporary copies is completely legal in C++

I just tried a few examples and you're right. I was going by this (under the Temporaries section), but it looks like it's incorrect (even though what is written there makes sense).

##### Share on other sites
Python objects have several functions available to them in order to deal with slices including the __getslice__ and __setslice__ methods. What you're doing in your first example is (implicitly) calling the __setslice__ method - it takes a slice of an object, modifies it, and reinserts it into the object. In your second example, you are implicitly calling __getslice__ which returns a copy of the slice selected.

Basically, whenever you have a assign operation following a slice, the __setslice__ method is called. Otherwise the __getslice__ method is called.

##### Share on other sites
CrimsonSun - Thank you for the thorough explanation, I understand now, though I still think it's strange that the second snippet doesn't cause an error.

##### Share on other sites
In your second example, you're just appending 7 to a temporary copy. If you don't do anything with this temporary, then the temporary is just thrown away. You can assign this modified temporary to a variable:
a = [1, 2, 3]b = a[:].append(7)

Now b contains [1, 2, 3, 7].

##### Share on other sites
Quote:
 a = [1, 2, 3]b = a[:].append(7)Now b contains [1, 2, 3, 7].

I just typed this, and the value of b is None because append() doesn't return anything.

##### Share on other sites
You're absolutely right, I made a mistake above - append doesn't return anything, so b gets the value of None. Please disregard my above post.

However, you can always assign a variable to the return value of a slice. Notice also that this is the only way to get a copy of a sequence such as a list.

If you have:
a = [1, 2, 3]

And then assign b to a:
b = a

Then you've assigned b to the same list as that of a. So anything that modifies the list accessed from a also modifies the list accessed from b (they are the same list!):

b[1] = 4
Now both a and b contain the list [1, 4, 3]. If you want to have a copy of the sequence in a (such that modification of the list accessed by a does not modify the list accessed by b), you just take the default slice:

b = a[:]

##### Share on other sites
Quote:
 Original post by CrimsonSunHowever, you can always assign a variable to the return value of a slice. Notice also that this is the only way to get a copy of a sequence such as a list.If you have:a = [1, 2, 3]And then assign b to a:b = aThen you've assigned b to the same list as that of a. So anything that modifies the list accessed from a also modifies the list accessed from b (they are the same list!):b[1] = 4Now both a and b contain the list [1, 4, 3]. If you want to have a copy of the sequence in a (such that modification of the list accessed by a does not modify the list accessed by b), you just take the default slice:b = a[:]

I don't understand how any of that is relevant to my question :)

If you write:

a[:].append(5)

you are modifying a temporary object that will cease to exist after that statement (or at least it will no longer be accessible). I can't think of an example where you would want to do this, so if you wrote something like this, you probably made a mistake, which is why I think the interpreter should flag this as an error.

Thanks for your help so far.

##### Share on other sites
It's not trivial for an interpreter to spot that such things are mistakes. Sometimes the function call on the right (eg. append() ) has side-effects that you're relying upon, so it can't assume it was an error. Maybe you were just testing the append() functionality, for example!

##### Share on other sites

This topic is 3775 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

This topic is now closed to further replies.

• 11
• 20
• 12
• 10
• 38
• ### Forum Statistics

• Total Topics
631401
• Total Posts
2999865
×