I have this:

import re

subs = []
def subcons(data):
    match = re.search(r'(<[a-z]{3})', data)
    if match:
        subs.append(match.group(0))
        data = data.replace(match.group(0), '')
        subcons(data)
    else:
        print data

    return data, subs


input = 'ABC <uvw <xyz some random data'
e, f = subcons(input)
print e
print f

The print statement in the else part of the function prints this:
ABC some random data
which is what I want.

The functio, however, returns this:
ABC <xyz some random data
not what I want. And:
['<uwv', '<xyz']
This is also what I want.

if I try to return the values from within the else nothing gets passed. Any ideas as to whay could cause this?

return data, subs

1st mistake:
you return a list, but as a return value in which you store that list, you put a variable f.
Initialize f as a list, like f=[] than put the e, f=subcons(input)

import re

l = []
def subcons(data):
    match = re.search(r'(<[a-z]{3})', data)
    if match:
        l.append(match.group(0))
        data = data.replace(match.group(0), '')
        subcons(data)
    return data, l


input = 'ABC <uvw <xyz some random data'
l1 = []
e, l1 = subcons(input)
print l

Edited 4 Years Ago by Lucaci Andrew

Thanks. The reason I didn't do this was because Python seemed happy for me to not explicitly state that the returned value was supposed to be a list. Actually Python seems quite generous in this regard. I can just do:
return {data:subs}
and when I ask it for:
the_dict = subcons(data)
it's happy to give me a dictionary with the value of data as the key and a list of items as the value.

I'm still not sore how to fix my problem though

Yeah, well in your case, the problem resides in how you think about recursion. You see, first when you call the function, it will replace in data the first group, but when you call the second time, data will be replaced again, resulting the correct form, but, when the function returns, it's inside the last call of it, and there is the 1st data, in which only the first part was replaced, so there you go, your disfunctionality.
Easy fix:

def subcons(data):
    match = re.search(r'(<[a-z]{3})', data)
    if match:
        l.append(match.group(0))
        if match != None:
            data = data.replace(match.group(0), '')
            data, f = subcons(data)
    return  data, l

keep the returned data from the last call in order to return the correct value.

I do not know how much this fuss is worth, looks like you are basically just after simple Python one-liner:

>>> d = 'ABC <uvw <xyz some random data'
>>> import string
>>> print([w for w in d.split() if w.startswith('<') and len(w)==4 and all(c in string.ascii_lowercase for c in w[1:])])
['<uvw', '<xyz']
>>> 

A while loop beats recursion in speed and simplicity:

import re

subs = []
data = 'ABC <uvw <xyz some random data'
while True:
    match = re.search(r'(<[a-z]{3})', data)
    if match:
        subs.append(match.group(0))
        data = data.replace(match.group(0), '')
    else:
        break

print("data = %s" % data)
print("subs = %s" % subs)

'''
data = ABC   some random data
subs = ['<uvw', '<xyz']
'''

This may help:

# a basic recursive function
# there is a limit to recursions
# sys.getrecursionlimit() --> usually 1000
# can be changed with
# sys.setrecursionlimit(x)

def factorial(n):
    """
    just an example, would be poor choice because of
    the many calls, each call uses another stack frame
    """
    # set an exit condition
    if n <= 1:
        return 1
    # a recursive function calls itself
    # with a changed argument value until
    # the exit condition is met (return is needed)
    return n * factorial(n - 1)

print(factorial(10))       # 3628800

import sys
print(sys.getrecursionlimit())  # 1000

I guess I still don't really 'get' recursion. Thanks for all the input. For now I'll just be using a while loop. Thanks for all the help!

This question has already been answered. Start a new discussion instead.