Getting string index out of range? python 3

2019-03-02 04:46发布

问题:

My program is supposed to take an input in form of a string and split into to strings, one with all the lower case letters, underscores and dots. The other one with all the upper cases, the pipes and the spaces. I am not supposed to use (for function)

def split_rec (letters):
    uppers = ""
    lowers = ""
    if letters[0].isupper() or letters[0] == "|" or letters[0].isspace():
        uppers += letters[0] + split_rec (letters[1:])
    elif letters[0].islower() or letters[0] == "_" or letters[0] == ".":
        lowers += letters[0] + split_rec (letters[1:])
    elif not letters:
        return lowers, uppers

Can you please tell me more about the error I'm getting?

if letters[0].isupper() or letters[0] == "|" or letters[0].isspace(): IndexError: string index out of range

回答1:

You have defined a recursive function: the split_rec calls split_rec (letters[1:]). Since a string has finite length, eventually you will pass it the empty string. So that means that you can not access the first character, since it has no first character.

You can solve that problem by using a guard:

def split_rec (letters):
    uppers = ""
    lowers = ""
    if not letters:
        return lowers, uppers
    if letters[0].isupper() or letters[0] == "|" or letters[0].isspace():
        uppers += letters[0] + split_rec (letters[1:])
    elif letters[0].islower() or letters[0] == "_" or letters[0] == ".":
        lowers += letters[0] + split_rec (letters[1:])
    elif not letters:
        return lowers, uppers

But this will not solve the problem: since split_rec returns a tuple of two strings, you can not add this to a character. You can solve the problem by using:

def split_rec (letters):
    if not letters:
        return lowers, uppers
    lowers, uppers = split_rec(letters[1:])
    if letters[0].isupper() or letters[0] == "|" or letters[0].isspace():
        uppers = letters[0] + uppers
    elif letters[0].islower() or letters[0] == "_" or letters[0] == ".":
        lowers = letters[0] + lowers
    return lowers, uppers

But nevertheless recursion that scales linear with input is in Python a bad idea: Python does not optimize recursive calls, and so one easily gets a StackOverflow exception (this has nothing to do with this site).

You better use a generator and join the strings together:

def split_rec (letters):
    uppers = ''.join(c for c in letters if c.isupper() or c == "|" or c.isspace())
    lowers = ''.join(c for c in letters if c.islower() or c == "_" or c == ".")
    return lowers, uppers


回答2:

as @willemVanOnsem pointed out, you are recursively calling this on the string minus the first char. Eventually, you are calling it on an empty string, which is why you get an index error. check that "letters" is not empty before doing anything else.

as a side note, I don't think your recursive call is going to do what you expect.

can you use a while loop? you mention not using a for loop? or do you have to use recursion?