Python - using a shared variable in a recursive function

流过昼夜 提交于 2020-04-08 09:42:07

问题


I'm using a recursive function to sort a list in Python, and I want to keep track of the number of sorts/merges as the function continues. However, when I declare/initialize the variable inside the function, it becomes a local variable inside each successive call of the function. If I declare the variable outside the function, the function thinks it doesn't exist (i.e. has no access to it). How can I share this value across different calls of the function?

I tried to use the "global" variable tag inside and outside the function like this:

global invcount  ## I tried here, with and without the global tag

def inv_sort (listIn):
    global invcount   ## and here, with and without the global tag

    if (invcount == undefined):  ## can't figure this part out
        invcount = 0

    #do stuff

But I cannot figure out how to check for the undefined status of the global variable and give it a value on the first recursion call (because on all successive recursions it should have a value and be defined).

My first thought was to return the variable out of each call of the function, but I can't figure out how to pass two objects out of the function, and I already have to pass the list out for the recursion sort to work. My second attempt to resolve this issue involved me adding the variable invcount to the list I'm passing as the last element with an identifier, like "i27". Then I could just check for the presence of the identifier (the letter i in this example) in the last element and if present pop() it off at the beginning of the function call and re-add it during the recursion. In practice this is becoming really convoluted and while it may work eventually, I'm wondering if there is a more practical or easier solution.

Is there a way to share a variable without directly passing/returning it?


回答1:


There's couple of things you can do. Taking your example you should modify it like this:

invcount = 0

def inv_sort (listIn):
    global invcount

    invcount += 1

    # do stuff

But this approach means that you should zero invcount before each call to inv_sort. So actually its better to return invcount as a part of result. For example using tuples like this:

def inv_sort(listIn):

    #somewhere in your code recursive call
    recursive_result, recursive_invcount = inv_sort(argument)

    # this_call_invcount includes recursive_invcount
    return this_call_result, this_call_invcount   



回答2:


An alternative might be using a default argument, e.g.:

def inv_sort(listIn, invcount=0):
    ...
    invcount += 1
    ...
    listIn, invcount = inv_sort(listIn, invcount)        
    ...
    return listIn, invcount

The downside of this is that your calls get slightly less neat:

l, _ = inv_sort(l) # i.e. ignore the second returned parameter

But this does mean that invcount automatically gets reset each time the function is called with a single argument (and also provides the opportunity to inject a value of invcount if necessary for testing: assert result, 6 == inv_sort(test, 5)).




回答3:


There's no such thing as an "undefined" variable in Python, and you don't need one.

Outside the function, set the variable to 0. Inside the loop, use the global keyword, then increment.

invcount = 0
def inv_sort (listIn):
    global invcount

    ... do stuff ...

    invcount += 1



回答4:


Assuming that you don't need to know the count inside the function, I would approach this using a decorator function:

import functools

def count_calls(f):
    @functools.wraps(f)
    def func(*args):
        func.count += 1
        return f(*args)
    func.count = 0
    return func

You can now decorate your recursive function:

@count_calls
def inv_sort(...):
    ...

And check or reset the count before or after calling it:

inv_sort.count = 0
l = inv_sort(l)
print(inv_sort.count)


来源:https://stackoverflow.com/questions/23762322/python-using-a-shared-variable-in-a-recursive-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!