Victor
Victor

Reputation: 447

What is the best way to return a stack variable from a recursive function?

I have a situation where I need to return the first item found in a list, How do I return it when I use recursion ?:

def get_hostname (ifname):
    try :
        # Do something to get hostname
        return hostname
    except IOError:
        return -1


def get_hostname_r(lst):
    if not lst:
        return False
    if get_hostname(lst[0]) != -1 :
        print 'Found ', get_hostname(lst[0])
        return get_hostname(lst[0]) # DOESNT WORK
    else :
        print 'Not found ', get_hostname(lst[0])
        get_hostname_r(lst[1:])

print 'return = ', get_hostname_r(['eth1','eth2','eth3','eth4','eth5' ]) 

I understand that the return goes back to the calling stack but Iam looking here for the best practices without using a global variable to get the value?

Upvotes: 0

Views: 49

Answers (2)

chepner
chepner

Reputation: 530872

First, if you can't do anything about the IO error, don't mask it by returning -1 ("What does -1 mean? Why didn't I get a host name back?"). Just document that get_hostname might raise an IOError.

def get_hostname(ifname):
    # Do stuff that might raise an IOError
    return hostname

The same goes for the recursive version. Either return a valid hostname, or raise an exception (or let an uncaught exception continue).

def get_hostname_r(lst):
    if not lst:
        raise IOError("Hostname not found")

    try:
        hostname = get_hostname(lst[0])
        print >>sys.stderr, 'Found {0}'.format(hostname)
        return hostname
    except IOError:
        print 'Not found with {0}'.format(lst[0])
        return get_hostname_r(lst[1:])

Of course, recursion isn't really the best way to write this; use a simple for loop instead to iterate over lst.

def get_hostname_iter(lst):
    for ifname in lst:
        try:
            return get_hostname(ifname)
        except IOError:
            continue
    raise IOError("Hostname not found")

Upvotes: 0

Daniel
Daniel

Reputation: 42748

You can simply return the value, the returned value is handed over the whole recursion stack:

def get_hostname_r(lst):
    if not lst:
        return False
    if get_hostname(lst[0]) != -1 :
        print 'Found ', get_hostname(lst[0])
        return get_hostname(lst[0])
    else:
        print 'Not found ', get_hostname(lst[0])
        return get_hostname_r(lst[1:])

But easier to read is a for-loop:

def get_hostname_r(interfaces):
    for interface in interfaces:
        result = get_hostname(interface)
        if result != -1:
            return result
    return False

Upvotes: 2

Related Questions