9

I am but a humble coding grasshopper and have a simple question.

Let:

x = ['this','is','a','list']

How come:

x[100:101]

outputs an empty list like expected, yet:

x[100]

is an error? Ditto for strings, please and thank you.

Engineero
  • 12,340
  • 5
  • 53
  • 75
Danny B
  • 355
  • 2
  • 13
  • 1
    I don't think the most voted answers there cover the exact answer here. Not voting to close for this particular dup. (Although there are probably others) – jsbueno Jul 16 '19 at 18:53
  • 1
    See the dupe but the explanation is specifically in [this answer](https://stackoverflow.com/a/4729334/5858851). – pault Jul 16 '19 at 18:53
  • 2
    What would expect it to yield for `x[100]` if no such element existed? And how would you distinguish between an element not existing from whatever value you chose above being element 100? – Scott Hunter Jul 16 '19 at 18:53
  • Thanks, though it does not explain why the slice operator does not give an error for out of index values yet the simple index operator does. Is this just the way the BDFLs made it? – Danny B Jul 16 '19 at 18:54
  • 2
    Can you tell between empty & non-empty slice ranges from what is returned? If so, why should an empty slice range be an error? – Scott Hunter Jul 16 '19 at 18:57
  • Okay, I am going to read the answer suggested by pault. – Danny B Jul 16 '19 at 18:57
  • @pault linked the correct answer. Very interesting! – Engineero Jul 16 '19 at 19:03
  • More: [Why python's list slicing doesn't produce index out of bound error?](https://stackoverflow.com/questions/22951107/why-pythons-list-slicing-doesnt-produce-index-out-of-bound-error) ... and... [Why does substring slicing with index out of range work?](https://stackoverflow.com/questions/9490058/why-does-substring-slicing-with-index-out-of-range-work) – wwii Jul 16 '19 at 19:05
  • @ScottHunter - I think your two comments above provide the bets explanation - they could be put in a short answer. – jsbueno Jul 16 '19 at 19:05
  • @jsbueno: Not since the question has been closed, but thanks. – Scott Hunter Jul 16 '19 at 19:07
  • It is obviously a nice question - so, it is been reopened. Just do it. – jsbueno Jul 16 '19 at 19:52

4 Answers4

6

It is basically a design choice of Python, and there is not really something right or wrong with either an error for x[100:101] versus giving an empty list.

Note that x[slice(...)] will always return a container (with the same type of x), while x[int] will always access the element at the specified position.

norok2
  • 25,683
  • 4
  • 73
  • 99
  • 1
    There *is* something wrong with attempts to access a non-existent element yielding a value. – Scott Hunter Jul 16 '19 at 18:55
  • I meant either choice of throwing an error for `x[100:101]` versus giving an empty `list`. – norok2 Jul 16 '19 at 18:56
  • Not actually, as there is no value yielded - it comes up with an empty container. At the end of the day, the net result is simpler code for otherwise special cases. – jsbueno Jul 16 '19 at 18:56
  • 1
    @jsbueno Which **is** a design choice, we are all grateful of – norok2 Jul 16 '19 at 18:57
  • An empty container *is* a value. – Scott Hunter Jul 16 '19 at 18:57
  • Yes, but you don't have any of the value sof the original container - and an empty container in Python has bool value "False" anyway - which simplifies things even further. – jsbueno Jul 16 '19 at 18:59
1

I think it was a design decision with Python. When selecting a range, Python will return everything it can even if the list indices are out of range. But if selecting a single key or index, Python will give an error if the key doesn’t exist.

I guess the logic is that if you are selecting a range, you probably don’t care as much about the items than if you were select each item individually

Jack
  • 486
  • 2
  • 5
  • 19
1

calling x[100:101] or x[100]calls thegetitem` function. according to the docs, this function should take in an integer or a slice object

https://docs.python.org/3/reference/datamodel.html#object.getitem

When you call x[100] you are trying to look up the non-existent 100th item, raising an error. There is no 100th object.

When you call x[100:101] you are passing in a slice object. this is handled differently. You get a slice of the list. In this case you get back [] because there are no items in that range.

Its still confusing.

ryati
  • 360
  • 3
  • 13
1

Python slicing uses right-open intervals.

This has nice properties like the slices [a:b] and [b:c] not overlapping. Also the length of the slice [a:b] is easy to calculate and verify: it is simply b - a, not b - a + 1, and an empty slice looks like [3:3], not [3:2]. [0:5] and [5:10] cuts a ten element list nicely in half.

One way to think of it is to imagine a ruler, where the indices being points between the elements:

|e0|e1|e2|
0  1  2  3

The index of an element is the number to the left (closer to zero).

The slice [0:2] goes from the | mark above zero, to the | mark above 2, spanning e1 and e2.

We can think of that 2 as referencing the right edge of element [1] rather than denoting the index of the excluded element [2].

Kaz
  • 55,781
  • 9
  • 100
  • 149