Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Global variable messes up my recursive function

I've just run into a tricky issue. The following code is supposed to split words into chunks of length numOfChar. The function calls itself, which makes it impossible to have the resulting list (res) inside the function. But if I keep it outside as a global variable, then every subsequent call of the function with different input values leads to a wrong result because res doesn't get cleared.

Can anyone help me out?

Here's the code (in case you are interested, this is problem 7-23 from PySchools.com):

res = []

def splitWord(word, numOfChar):        
    if len(word) > 0:
        res.append(word[:numOfChar])
        splitWord(word[numOfChar:], numOfChar)    
    return res

print splitWord('google', 2)
print splitWord('google', 3)
print splitWord('apple', 1)
print splitWord('apple', 4)
like image 840
coltonpagefault Avatar asked Dec 07 '25 07:12

coltonpagefault


2 Answers

A pure recursive function should not modify the global state, this counts as a side effect.

Instead of appending-and-recursion, try this:

def splitWord(word, numOfChar): 
    if len(word) > 0:
        return [word[:numOfChar]] + splitWord(word[numOfChar:], numOfChar)
    else:
        return []

Here, you chop the word into pieces one piece at a time, on every call while going down, and then rebuild the pieces into a list while going up.

This is a common pattern called tail recursion.

P.S. As @e-satis notes, recursion is not an efficient way to do this in Python. See also @e-satis's answer for a more elaborate example of tail recursion, along with a more Pythonic way to solve the problem using generators.

like image 170
Helgi Avatar answered Dec 08 '25 22:12

Helgi


Recursion is completely unnecessary here:

def splitWord(word, numOfChar):
   return [word[i:i+numOfChar] for i in xrange(0, len(word), numOfChar)]

If you insist on a recursive solution, it is a good idea to avoid global variables (they make it really tricky to reason about what's going on). Here is one way to do it:

def splitWord(word, numOfChar):
   if len(word) > 0:
      return [word[:numOfChar]] + splitWord(word[numOfChar:], numOfChar)
   else:
      return []
like image 45
NPE Avatar answered Dec 08 '25 21:12

NPE



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!