-1

I am trying to find the length of the string with out using the inbuilt len() function. Here's my python code:

increment = -1
def lenRecur(aStr):
    '''
    aStr: a string

    returns: int, the length of aStr
    '''
    global increment

    if aStr == '':
        return increment
    else:
        increment += 1
        return lenRecur (aStr[increment:])
print lenRecur ("abcdefq")

The result I am expecting is 7 but what I got was 4.What I realized was when the increment became 2, the value pass to the lenRecur (aStr[increment:]) was "defq". Which means aStr[2:] is evaluated as "defq" instead of "cdefq".

Why this is happening?

Alok
  • 2,629
  • 4
  • 28
  • 40
Vijayenthiran
  • 114
  • 1
  • 10

3 Answers3

3

Your function should not depend on external variables.

def lenRecur(aStr):
    '''
    aStr: a string

    returns: int, the length of aStr
    '''
    if aStr == '':
        return 0
    else:
        return 1 + lenRecur(aStr[1:])


print lenRecur("abcdefq")
Maxime Chéramy
  • 17,761
  • 8
  • 54
  • 75
0

As an other option, you could write this:

def lenRecur(aStr):
    return _lenRecur(aStr, 0)

def _lenRecur(aStr, acc):
    if not aStr:
        return acc

    return _lenRecur(aStr[1:], acc+1)

A noticed by @gboffi in his answer, it is commonly accepted in Python to use a default argument instead of using of an helper function:

def lenRecur(aStr, acc = 0):
    if not aStr:
        return acc

    return lenRecur(aStr[1:], acc+1)

The choice of one form or the other will depend how much you want/don't want to allow the called to set the initial accumulator value to something else than 0.

Anyway, the interesting point here is in using an accumulator as the second parameter. That way, you have proper tail recursion. Unfortunately, this is not properly optimized by Python. But this is a good habit as many other languages have such optimization. And this will be a required skill if you switch someday to functional programing language.

Community
  • 1
  • 1
Sylvain Leroux
  • 50,096
  • 7
  • 103
  • 125
0

A common idiom is to use a default argument:

>>> def l(s, c=0): return l(s[1:], c+1) if s else c

This kind of solution works with anything that can be sliced

>>> l('pip')
3
>>> l([1,2,3])
3
>>> l('')
0
>>> l([])
0
>>> 
gboffi
  • 22,939
  • 8
  • 54
  • 85