3
list1 = [1, 2, 3, 4]  
element = list1[1:][1]   
print(element)

Why does it print 3?

How is this evaluated? Does it first take the elements of list1 that are from index 1: then it takes the 1 index of that?

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
Emma Pascoe
  • 137
  • 1
  • 7
  • python evaluates from left to right in that case. – Jean-François Fabre Oct 15 '18 at 20:23
  • Which part don't you understand, `[1:]` or `[1]`? I think that you think `list1[1:]` is `[3, 4]`, which it's not. – Patrick Haugh Oct 15 '18 at 20:23
  • 1
    `[1:]` is a slice of your list that starts at index one and goes to the end of the list (indices start at zero normally). So this produces `[2,3,4]` but then you ask for the middle element of that list with `[1]`, which is `3`. Recall that the list index starts at `0`. – Matt Cremeens Oct 15 '18 at 20:24

1 Answers1

4

Python's grammar specifies how it is evaluated, since it constructs a syntax tree of your program.

Without going much into technical detail, such indexing is left recursive. This means that:

foo[bar][qux]

is short for:

(foo[bar])[qux]

so such indices are evaluated left-to-right.

It is evaluated like:

list1 = [1, 2, 3, 4]
temp = list1[1:]    # create a sublist starting from the second item (index is 1)
element = temp[1]   # obtain the second item of temp (index is 1)

(of course in reality, no temp variable is created, but the list itself is a real object stored in memory, and thus also might change state, etc.).

So first we slice starting from the second item, this results in a list [2, 3, 4], and then we obtain the second item of that list, so 3.

Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • Thank you for explaining, very helpful! – Emma Pascoe Oct 15 '18 at 20:25
  • *of course in reality, no temp variable is created* - well it *is* created but isn't bound to anything so just doesn't remain available at the end of the statement. – Jon Clements Oct 15 '18 at 20:31
  • @JonClements: well I think it does not create a *variable*, only an *accumulator*. For example you can not inspect the call-stack and see the intermediate result as a (named) identifier. – Willem Van Onsem Oct 15 '18 at 20:31
  • @WillemVanOnsem nope... a new list is created by slicing - so if you had a 1000 element list, you create a new one that's 999 elements, then index in to that... the 999 list isn't bound to anything so is free to be garbage collected at the end of the statement... but it's still created... – Jon Clements Oct 15 '18 at 20:34
  • @JonClements: yes, but that is - I think - an object, not a *variable*. A variable - based on how I learned it in computer science classes - is a "symbolic name associated to a value". – Willem Van Onsem Oct 15 '18 at 20:35
  • I think what I'm saying is that it sounds like you're implying `lsit1[1:]` doesn't need to create something to apply the `[1]` to... it does - it just has no name and immediately available for garbage collection after. – Jon Clements Oct 15 '18 at 20:36