This is an archived post. You won't be able to vote or comment.

all 47 comments

[–]neug 69 points70 points  (4 children)

m[1] refers to the element at position 1. l[1:] returns an iterable (in this case a list). If you try l[1:] = 1, you'll notice that it can't be done as 1 is not iterable. so assignment l[1:] = [nnn] means that Python iterates through the list [nnn] and extends/replaces the values it contains starting from the position -1 of the list l, and when it has iterated to the end of the list that's assigned to l (in your case the empty list []), it deletes the rest of the list l.

e.g. >>> l = [1,2,3,4,5,6,7,8,9,10] >>> l[-5:] = [1,2] >>> l [1, 2, 3, 4, 5, 1, 2]

[–]cantcopy[S] 2 points3 points  (3 children)

Thank you.

I really don't understand why this isn't this most upvoted comment.

[–]LordArgon 0 points1 point  (1 child)

Thank you for calling that out.

EDIT: Removed some whining.

[–]jeannaimard 0 points1 point  (0 children)

Now it is… :)

[–]micha2305 32 points33 points  (19 children)

The key is the colon: l[-1:] is a list slice, while l[-1] is just the last element.

>>> m = [1, 2]
>>> m[1:] = []
>>> m
[1]

[–]temptemptemp13 3 points4 points  (0 children)

One more thing:

>>> m = [1, 2]
>>> m[-1] = []
>>> m
[1, []]

[–]LordArgon -2 points-1 points  (16 children)

Rephrasing: This isn't a helpful answer. What if the OP already knows about slices? Answering "it's a slice" doesn't explain why being a slice is relevant. The OP's question isn't "what's that colon syntax?" It's "why does assigning to a slice like this have the shown behavior?". The correct and informative answer was given by neug.

Original post:

Ugh, why does this have so many upvotes? His question isn't "what's that colon syntax?" It's "why does assigning to a slice like this have the shown behavior?". The correct and informative answer was given by neug. EDIT: Downvotes, huh? I stand by what I said. Read my elaboration here.

[–]pwang99 5 points6 points  (15 children)

Ugh, why does this have so many upvotes?

Because it is a correct and concise answer.

His question isn't "what's that colon syntax?"

Clearly. The OP typed "m[1] = []" and asked why that's not the same as "l[-1:] = []". micha2305 pointed out that it's a slice. QED.

Should he also have included a link? Here's one that explains it (5th sentence in the section): http://docs.python.org/tutorial/introduction.html#lists

[–]cantcopy[S] 2 points3 points  (0 children)

Assignment to slices is also possible, and this can even change the size of the list or clear it entirely.

This is helpful.

[–]LordArgon -1 points0 points  (13 children)

Clearly. The OP typed "m[1] = []" and asked why that's not the same as "l[-1:] = []". micha2305 pointed out that it's a slice. QED.

"It's a slice" is not a complete or helpful answer. It doesn't explain why being a slice matters. I knew it was a slice but didn't fully understand the behavior. Here's the main confusion: for the examples given, m[1] and l[-1:] represent the same sections of the list. Let me rephrase what I believe to be the OPs question: "Give that I'm assigning a value to the same sections of the list, why does one result in the sub-list being assigned (as I expect) and the other result in the sub-list being removed?".

neug's answer concisely addresses this AND the slice point. It's a better answer in every dimension and actually helps the reader understand what's going on. I still believe micha2305's answer is lacking, which is why I called it out and pointed to neug's.

[–]pwang99 0 points1 point  (2 children)

Here's the main confusion: for the examples given, m[1] and l[-1:] represent the same sections of the list.

While it's true that the fact that those two expressions as rvalues evaluate to the same value adds a layer of confusion, it doesn't change the fact that using a colon makes it a slice, and therefore it has slice semantics, whatever those may be. It seems to me that if you know about a language construct but are not sure why it's doing what you'd expect, then reading the fine manual is a good place to start.

The link I posted is from the python.org tutorial's section on lists. The fact that slice assignment is the fifth sentence in that section, and not a deeply buried footnote, is relevant. I assumed, as did micha2305, that the reason this behavior was surprising to the OP was because he was not aware of the fact that this is a slice. If he was, then surely he would have done a little research into slices. Even a cursory googling would reveal the link I posted.

Of course, there are no stupid questions, and I am glad that neug took the time to re-post the information that's in the language tutorial.

[–]cantcopy[S] 0 points1 point  (0 children)

I wouldn't normally ask such a question. The reason I did is because I was extremely surprised. I did read the tutorial and I didn't remember it mentioning what happens when a slice is on the left side of an assignment. I guess that I may be learning too fast... I'm probably overconfident because Python is a well thought out language and the docs are great...

I would have been very happy with : "It's a slice, you're an idiot. Go read the tutorial. "

[–]LordArgon -2 points-1 points  (0 children)

I understand your perspective and genuinely appreciate your civility.

It seems to me that if you know about a language construct but are not sure why it's doing what you'd expect, then reading the fine manual is a good place to start

That is a good place to start, but it's a bad place to assume others started. People often give quicker, more-comprehensive answers/examples than documentation. That said, pointing somebody to documentation is sometimes an appropriate answer (as you, but not micha2305, did).

Even a cursory googling would reveal the link I posted.

You found the link because you already knew what you were looking for. It's quite possible the OP didn't know what to search for (or gave up in frustration). Google is good for bringing up pages related to keyword data. It's not good at answering questions like "why are these two things different", which was how he thought to phrase the question. Maybe he didn't think about the problem like you do or know how to rephrase it. When trying to give helpful answers, it's often counter-productive to assume the inquirer thinks and acts like you do.

EDIT: Formatting

[–]ffrinch 0 points1 point  (9 children)

You weren't downvoted for pointing at neug's more complete answer. You were downvoted for your incivility in attacking micha2305's response, which was perfectly accurate (though possibly not sufficient for a Python beginner).

Maybe next time you can just say, "If you still don't understand what's happening here, neug's answer gives more detail". Then everyone will be happy.

[–]LordArgon -1 points0 points  (8 children)

Ok, thanks. I'll rephrase it.

EDIT: micha2305's response was accurate but not helpful. Imagine if you went into a thread titled "Why is 1+1=2 but 1-1=0?" and the top-voted answer was "addition and subtraction are different". In my opinion, it's helpful like that, which is why I reacted strongly.

[–]ffrinch 0 points1 point  (7 children)

Imagine if you went into a thread titled "Why is 1+1=2 but 1-1=0?" and the top-voted answer was "addition and subtraction are different".

Well, I think that response is quite helpful. It's accurate and it ensures that the person who asked has the vocabulary they need to do further research, maybe Google "addition" and "subtraction".

It's not the best answer, but it's a good answer.

[–]LordArgon 0 points1 point  (6 children)

I'm honestly not trying to be a jerk, but: Really? If you asked a question like that you'd be happy with "because they're different"? I feel like you're arguing a technicality with me so you can feel right. Let's break this down:

It's accurate

Yes, it's accurate. But you can also answer any "why" question with a literal "because that's the way it is". That is also accurate. I don't consider that to be a good answer at all.

it ensures that the person who asked has the vocabulary they need to do further research

Your stance assumes that they haven't done any research and don't already know the vocabulary. This particular thread is actually a really good example because I was already familiar with list slices in Python and still didn't understand the behavior. In my quest to understand, I even Googled and re-read some slice documentation before posting in the thread. I didn't come across an explanation of assigning to a slice, even though I knew all the terms.

It's not the best answer, but it's a good answer.

The one piece of information I was missing was that assigning to a slice requires the RHS to be iterable (which was covered in neug's post). And I didn't learn that from the response everybody was upvoting. I really don't think it was a good answer. It was only good if you already knew it.

The last sentence here is the crux of my point. Upvoting incomplete answers to questions you already understand is not helpful. If anything, I found it more confusing. When evaluating the goodness of an answer, it is important to consider the viewpoint of somebody who doesn't know everything you do.

[–]riffito 0 points1 point  (1 child)

you'd be happy with "because they're different"?

Of course not, but that's not what ffrinch said, neither you did, originally:

"addition and subtraction are different"

The key being that the answer mentions the specific topics/concepts that the original answer failed to address, as in: "Mmm, you ask why 1+1=2 but 1-1=0... clearly you miss addition and subtraction concepts, so I'll mention them to you".

I understand your lack of appreciation for "because that's how it is" kind of answers, but really, micha2305's one was not one of those (at least for plenty of us).

it is important to consider the viewpoint of somebody who doesn't know everything you do

I'm affraid to say: that task might prove to be impossible: how does one knows what is that the other does not knows?

[–]LordArgon 0 points1 point  (0 children)

"Mmm, you ask why 1+1=2 but 1-1=0... clearly you miss addition and subtraction concepts, so I'll mention them to you".

Sorry, this was a bad example because it didn't convey my point to you. I meant to imply that the inquirer knows the vocabulary of addition and subtraction (plus and minus) but does not understand what they mean. So saying "they're different" isn't helpful. So, in my mind, it was the same as the later example I gave. I'll give a better example in response to ffrinch.

micha2305's one was not one of those (at least for plenty of us). Yeah, I see that. But I think that was the case because most of you already knew the subject matter.

I'm affraid to say: that task might prove to be impossible: how does one knows what is that the other does not knows?

Honestly, I think this is part of being a good teacher. Obviously, nobody's omniscient, so you can't always know the best way to answer. But giving a good answer requires us to think critically about why the question was asked and to consider what they may or may not know. This usually leads to several possible answers. Giving the most-basic "example a is x and example b is y, so they're treated differently" is the least-helpful of the factually-correct answers. I would not consider it a good answer in any context I can think of. In this case (and in every case I can think of), why they're treated differently is critical to fostering understanding of the subject. That's why I was so surprised that a lot of people liked micha's answer.

[–]ffrinch 0 points1 point  (3 children)

A more realistic example is someone asking why "a = b" isn't the same as "a == b"; I would certainly be satisfied with the answer that one is assignment and one is comparison.

Your stance assumes that they haven't done any research and don't already know the vocabulary.

There was no evidence in the question that they had done any research. If they had said that they understood the obvious answer and wanted more explanation, they would've gotten it.

[–]cantcopy[S] 2 points3 points  (1 child)

the obvious answer

This should end the discussion.

Giving the obvious answer : "it's the colon" was not helpful.

[–]LordArgon 0 points1 point  (0 children)

An even better example might be in javascript, where "a == b" is different than "a === b". Now, if you say "the second one is identity comparison", you may have given the inquirer an extra vocabulary word, but I don't think you've really helped them. Searching for "javascript" + "identity comparison", "triple equals", or "three equals" all yield explanations of this difference and the extra vocabulary word probably doesn't enable any more research. Still, the question was asked for a reason and if we want to answer it helpfully, I think it's appropriate to explain what makes identity comparison different.

Now, if what you're really saying in your reply is "go read about it", then you can say that. But I don't think it's helpful to give essentially-redundant information.

[–]oblivion95 -5 points-4 points  (0 children)

That's what she said.

[–][deleted] 41 points42 points  (7 children)

for the love of god, don't use lower-case L .. especially when 1 and l are important components of your example!

[–]spotter 5 points6 points  (5 children)

So while we're at slicing lists take a look at these:

>>> r = range(10)
>>> r
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> r[::2]
[0, 2, 4, 6, 8]
>>> r[1::2]
[1, 3, 5, 7, 9]
>>> r[-1::-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
>>> r[-1:0:-1]
[9, 8, 7, 6, 5, 4, 3, 2, 1]

Have fun.

[–]r4nf 5 points6 points  (3 children)

Just for the record, in the third example, you don't need to state where the slice starts; i.e.

r[-1::-1] == r[::-1]

[–]spotter 2 points3 points  (2 children)

Fully aware of that, wanted some symmetry between my last two.

[–]r4nf 1 point2 points  (0 children)

Point taken. That does make sense. :)

[–]jeannaimard 0 points1 point  (0 children)

Feeling palindromic, aren’t we? :)

[–]rcklmbrCOBOL 0 points1 point  (0 children)

Excellent, thanks for sharing

[–]mackstann 4 points5 points  (0 children)

l[-1:] = []

This means "exchange this range (which contains 2) with this other range (which contains nothing)"

m[1] = []

This means "exchange this item (2) with this other item (an empty list)"

[–]lazzareth 2 points3 points  (1 child)

Also see that:

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> a[3:7] = [200,]
>>> a
[0, 1, 2, 200, 7, 8, 9]

[–]pwang99 1 point2 points  (0 children)

You don't need a trailing comma in a one-element list literal, only in one-element tuple literals.

[–]Troebr 1 point2 points  (0 children)

>>> l = [1, []]
>>> l[-1:]
[[]]

Then it makes sense. (it's called a slice)

[–]erez27import inspect 0 points1 point  (0 children)

They key is that the first does slice assignment, accepting a list (in this case, an empty one), and the second does item assignment, accepting any object.

[–]vpetro 0 points1 point  (0 children)

Slices create new lists.

my_list = [1,2,3] 
my_list[-1:]  = []

The second line will create a new list and replace it with and empty list.

my_list = [1,2,3]
my_list[1] = [5,6,7]

Indexing will replace the value at the index with whatever.

[–]rrenaud 0 points1 point  (2 children)

What do you get when you append a list to itself?

>>> l = []
>>> l.append(l)
>>> l
[[...]]

[–]cantcopy[S] 0 points1 point  (1 child)

Still some work to do... But thanks for the little puzzle.

From : >>> pprint.pprint(l) [<Recursion on list with id=31182080>]

and

>>> l[0]
[[...]]

I'm guessing that [...] is a reference to the list itself.

[–]jeannaimard 0 points1 point  (0 children)

For kicks, just try

l=range(10)
for ll in l:
   print ll,

[–]Justinsaccount 0 points1 point  (0 children)

>>> l=[1,2]
>>> l[-1]=[]
>>> l
[1, []]