16

OK, i'm using Python 2.7.3 and here is my code:

def lenRecur(s): 

    count = 0

    def isChar(c):
        c = c.lower()
        ans=''
        for s in c:
            if s in 'abcdefghijklmnopqrstuvwxyz':
                ans += s
        return ans

    def leng(s):
        global count
        if len(s)==0:
            return count
        else:
            count += 1
            return leng(s[1:])

    return leng(isChar(s))

I'm trying to modify the variable count inside the leng function. Here are the things that I've tried:

  1. If I put the variable count outside the lenRecur function it works fine the first time, but if I try again without restarting python shell, the count (obviously) doesn't restart, so it keeps adding.
  2. If I change the count += 1 line for count = 1 it also works, but the output is (obviously) one.

So, my goal here is to get the length of the string using recursion, but I don't know how to keep track of the number of letters. I've searched for information about global variables, but I am still stuck. I don't know if i haven't understood it yet, or if I have a problem in my code.

Thanks in advance!

1
  • can't see recursion itself. Commented Jun 27, 2013 at 11:35

6 Answers 6

31

count in lenRecur is not a global. It is a scoped variable.

You'll need to use Python 3 before you can make that work in this way; you are looking for the nonlocal statement added to Python 3.

In Python 2, you can work around this limitation by using a mutable (such as a list) for count instead:

def lenRecur(s): 

    count = [0]

    # ...

    def leng(s):
        if len(s)==0:
            return count[0]
        else:
            count[0] += 1
            return lenIter(s[1:])

Now you are no longer altering the count name itself; it remains unchanged, it keeps referring to the same list. All you are doing is altering the first element contained in the count list.

An alternative 'spelling' would be to make count a function attribute:

def lenRecur(s): 

    # ...

    def leng(s):
        if len(s)==0:
            return leng.count
        else:
            leng.count += 1
            return lenIter(s[1:])

    leng.count = 0

Now count is no longer local to lenRecur(); it has become an attribute on the unchanging lenRecur() function instead.

For your specific problem, you are actually overthinking things. Just have the recursion do the summing:

def lenRecur(s):
    def characters_only(s):
        return ''.join([c for c in s if c.isalpha()])

    def len_recursive(s):
        if not s:
            return 0
        return 1 + len_recursive(s[1:])

    return len_recursive(characters_only(s))

Demo:

>>> def lenRecur(s):
...     def characters_only(s):
...         return ''.join([c for c in s if c.isalpha()])
...     def len_recursive(s):
...         if not s:
...             return 0
...         return 1 + len_recursive(s[1:])
...     return len_recursive(characters_only(s))
... 
>>> lenRecur('The Quick Brown Fox')
16
Sign up to request clarification or add additional context in comments.

5 Comments

Is there any way to do this in Python 2.7?
or You can pass count as a parameter to leng function
Ok that worked for me! May I ask why did a list work and not a normal variable?
I think I have been one step ahead of your questions so far; I edited in an explanation as to why count = [0] works; did you see that already?
Yes yes!! Thank you very much! That's what I call a good answer :)
9

I think You can pass count as second argument

def anything(s):
    def leng(s, count):
        if not s:
            return count
        return leng(s[1:], count + 1)

    return leng(isChar(s), 0)

this should work better than muting objects from outer scope such as using mutable objects (list or dict) or monkey-patching function itself for example.

1 Comment

I posted the same answer. Didn't see your post there. I guess I am late as usual :-)
3

You need to make the variable count a function variable like

def lenRecur(s):
    lenRecur.count = 0

However, I see a few problems with the code.

1) If you are trying to find the number of alphabets in a string through recursion, this one will do:

def lenRecur(s):
    def leng(s, count = 0):
            if not s:
                    return count
            else:
                    count += int(s[0].isalpha())
                    return leng(s[1:], count)
    return leng(s)

But still I would prefer having a single function to do the task, like there will be no leng method at all.

2) If your goal is just to find the number of alphabets in a string, I would prefer list comprehension

def alphalen(s):
    return sum([1 for ch in s if ch.isalpha()])

If this is anything other than learning purpose, I suggest you to avoid recursion. Because, the solution cannot be used for larger strings(lets say, finding the alphabet count from contents of a file). You might hit the RunTimeError of Maximum Recursion Depth Exceeded.

Even though you can work around this through setting the recursion depth through setrecursionlimit function, I suggest you to go for other easy ways. More info on setting the recursionlimit here.

Comments

1

Define it outside all function definitions, if you want to use it as a global variable:

count = 0
def lenRecur(s): 

or define it as a function attribute:

def lenRecur(s): 
    lenRecur.count = 0
    def isChar(c):

This has been fixed in py3.x where you can use the nonlocal statement:

def leng(s):
    nonlocal count
    if len(s)==0:

2 Comments

If I difine it outside the function lenRecur is the first statement I said that I tried. Thanks anyway!
@CarlesMitjans I guess I missed that detail, You can define it as a function attribute.
0

You don't need count. The below function should work.


    def leng(s):
        if not s:
            return 0
        return 1 + leng(s[1:])

Comments

-1

Global variable in recursion is very tricky as the depth reaches to its last state and starts to return back to the first recursive call the values of local variables change so we use global variables. the issue with global variables is that when u run the func multiple times the global variable doesn't reset.

1 Comment

This question already has a number of answers including explanations and code samples, provided 8 years ago. It doesn't seem that your answer adds anything new to that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.