stringpython-3.xsliceindex-error

Why is there no IndexError when I use index numbers larger then len(string) while slicing?


When I use a index number larger then the length of a string I rightfully get an IndexError in Python, e.g.:

string = "uphill"  
print(string[12])

But if I slice the string it somehow seems to be okay to use index numbers larger than the string, as the following code does not create an IndexError:

string = "uphill"
print(string[0:12])

Why is this the case? This seems rather implicit to me, as I would expect an IndexError in this case also. If this is rather obvious I am sorry, but I could ne find anything related.


Solution

  • I found a well explained answer to this question in this article: https://lerner.co.il/2018/06/08/python-parentheses-primer/

    Note: the following answer is from the article, not by me.

    "

    You can get an IndexError exception if you ask for a single index beyond the boundaries of a sequence. But slices don’t have in such problems; they’ll just stop at the start or end of your string. ... How do the square brackets distinguish between an individual index and a slice? The answer: They don’t. In both cases, the getitem method is being invoked. It’s up to getitem to check to see what kind of value it got for the “index” parameter.

    But wait: If we pass an integer or string (or even a tuple) to square brackets, we know what type will be passed along. What type is passed to our method if we use a slice?

    In [55]: class Foo(object):
    ...:         def __getitem__(self, index):
    ...:             print(f"index = {index}, type(index) = {type(index)}")
    ...:
    
    
    In [56]: f = Foo()
    
    In [57]: f[100]
    index = 100, type(index) = <class 'int'>
    
    In [58]: f[5:100]
    index = slice(5, 100, None), type(index) = <class 'slice'>
    
    In [59]: f[5:100:3]
    index = slice(5, 100, 3), type(index) = <class 'slice'>
    

    Notice that in the first case, as expected, we get an integer. But in the second and third cases, we get a slice object. We can create these manually, if we want; “slice” is in the “bulitin” namespace, along with str, int, dict, and other favorites. And as you can see from its printed representation, we can call “slice” much as we do “range”, with start, stop, and step-size arguments.