[ACCEPTED]-How to maintain lists and dictionaries between function calls in Python?-function-calls

Accepted answer
Score: 18

You might be talking about a callable object.

class MyFunction( object ):
    def __init__( self ):
        self.rememberThis= dict()
    def __call__( self, arg1, arg2 ):
        # do something
        rememberThis['a'] = arg1
        return someValue

myFunction= MyFunction()

From 2 then on, use myFunction as a simple function. You 1 can access the rememberThis dictionary using myFunction.rememberThis.

Score: 15

You could use a static variable:

def foo(k, v):
  foo.a[k] = v
foo.a = {'a': 1, 'b': 2, 'c': 3}

foo('a', 100)
foo('b', 200)

print foo.a

0

Score: 8

Rather than forcing globals on the code 15 base (that can be the decision of the caller) I 14 prefer the idea of keeping the state related 13 to an instance of the function. A class 12 is good for this but doesn't communicate 11 well what you are trying to accomplish and 10 can be a bit verbose. Taking advantage 9 of closures is, in my opinion, a lot cleaner.

def function_the_world_sees():
    a = {'a':1,'b':2,'c':3}

    def actual_function(arg0, arg1):
        a[arg0] = arg1
        return a

    return actual_function
stateful_function = function_the_world_sees()

stateful_function("b", 100)    
stateful_function("b", 200)

The 8 main caution to keep in mind is that when 7 you make assignments in "actual_function", they 6 occur within "actual_function". This means 5 you can't reassign a to a different variable. The 4 work arounds I use are to put all of my 3 variables I plan to reassign into either 2 into a single element list per variable 1 or a dictionary.

Score: 6

If 'a' is being created inside the function. It 5 is going out of scope. Simply create it 4 outside the function(and before the function 3 is called). By doing this the list/hash 2 will not be deleted after the program leaves 1 the function.

a = {'a':1,'b':2,'c':3}

# call you funciton here
Score: 3

You can 'cheat' using Python's behavior 13 for default arguments. Default arguments 12 are only evaluated once; they get reused 11 for every call of the function.

>>> def testFunction(persistent_dict={'a': 0}):
...     persistent_dict['a'] += 1
...     print persistent_dict['a']
...
>>> testFunction()
1
>>> testFunction()
2

This isn't 10 the most elegant solution; if someone calls 9 the function and passes in a parameter it 8 will override the default, which probably 7 isn't what you want.

If you just want a quick 6 and dirty way to get the results, that will 5 work. If you're doing something more complicated 4 it might be better to factor it out into 3 a class like S. Lott mentioned.

EDIT: Renamed 2 the dictionary so it wouldn't hide the builtin 1 dict as per the comment below.

Score: 3

This question doesn't have an elegant answer, in 19 my opinion. The options are callable objects, default 18 values, and attribute hacks. Callable objects 17 are the right answer, but they bring in 16 a lot of structure for what would be a single 15 "static" declaration in another language. Default 14 values are a minor change to the code, but 13 it's kludgy and can be confusing to a new 12 python programmer looking at your code. I 11 don't like them because their existence 10 isn't hidden from anyone who might be looking 9 at your API.

I generally go with an attribute 8 hack. My preferred method is:

def myfunct():
    if not hasattr(myfunct, 'state'): myfunct.state = list()
    # access myfunct.state in the body however you want

This keeps 7 the declaration of the state in the first 6 line of the function where it belongs, as 5 well as keeping myfunct as a function. The 4 downside is you do the attribute check every 3 time you call the function. This is almost 2 certainly not going to be a bottleneck in 1 most code.

Score: 3

Personally, I like the idea of the global 4 statement. It doesn't introduce a global 3 variable but states that a local identifier 2 actually refers to one in the global namespace.

d = dict()
l = list()
def foo(bar, baz):
    global d
    global l
    l.append(bar, baz)
    d[bar] = baz

In 1 python 3.0 there is also a "nonlocal" statement.

More Related questions