Getting string index out of range? python 3

后端 未结 2 1692
灰色年华
灰色年华 2021-01-25 06:59

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 uppe

2条回答
  •  独厮守ぢ
    2021-01-25 07:32

    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
    

提交回复
热议问题