Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global variables in recursion. Python

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!

like image 320
Carles Mitjans Avatar asked Jun 27 '13 11:06

Carles Mitjans


2 Answers

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
like image 167
Martijn Pieters Avatar answered Sep 19 '22 11:09

Martijn Pieters


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.

like image 20
oleg Avatar answered Sep 19 '22 11:09

oleg