1

I have a function that returns a dictionary.

I would like to be able to access and work with that dictionary many times in the code, without the need to be calling the function that produces that dictionary every time. In other words, call the function once, but work with the dictionary that it returns many times.

So this way, the dictionary is constructed only once (and maybe stored somewhere?), but called and utilised many times in the script.

def function_to_produce_dict():
    dict = {}
    # something
    # something that builds the dictionary 
    return dict 


create_dict = function_to_product_dict()

# other code that will need to work with the create_dict dictionary. 
# without the need to keep constructing it any time that we need it. 

I have read other posts such as: Access a function variable outside the function without using `global`

But I am not sure that by declaring the dictionary as global withing the function_to_produce_dict() is going to make the dictionary accessible without having to build it every time, by calling the function again and again.

Is this possible?

Community
  • 1
  • 1
HR123r
  • 181
  • 2
  • 10

2 Answers2

5

Maybe I'm not understanding, but you're already saving it in create_dict; just continue to use the dict in create_dict. It's not being constructed each time once you store it in create_dict.

Perhaps you should rename it, as create_dict sounds like a function that creates a dict. Maybe that's related to your confusion on this?

Cyphase
  • 11,502
  • 2
  • 31
  • 32
  • Oh really? I didn't know that. So say if I call the function_to_produce_dict() for the first time, and then I use the variable 'create_dict' then it means that this is my dictionary!! This is so logical, I am such a novice I missed this simple thing! So as long that I don't call the function again and just use the variable 'create_dict' the dictionary is not constructed again. Thank you for clearing it up for me!! – HR123r Aug 09 '15 at 23:50
  • I think you've got it; glad I could help :). Just to clarify; `function_to_produce_dict()` returns a dict, which you are assigning to the variable `create_dict`. Now you can use that variable to access the dict however you like; it's not going to run the function every time. – Cyphase Aug 09 '15 at 23:55
2

It's a little unclear what is stopping you from just using the dictionary as usual. Do you have a situation such as the following?

def function_to_produce_dict():
    ...

def foo():
    dct = function_to_produce_dict()
    # do something to dct
    ...

def bar():
    dct = function_to_produce_dict()
    # do something to dct
    ...

foo()
bar()

In such a case, you might want foo and bar to take an argument that is an already-constructed dct:

def foo(dct):
    # do something with dct

If you really can't get around it, you can cache the result of creating the dictionary so that it's really only computed once:

def _cached_function_to_compute_dict():
    dct = None
    def wrapper():
        if dct is None:
            dct = _function_to_compute_dict()
        return dct
    return wrapper

def _function_to_compute_dict():
    # create and return a dictionary
    return dct

function_to_compute_dict = _cached_function_to_compute_dict()

This is just a specialized memoization decorator... you could get a lot fancier, use functools.partial to preserve function metadata, etc.

jme
  • 19,895
  • 6
  • 41
  • 39
  • thank you. In one of the cases indeed, I will need to use the dictionary from within another function. So in this case, I would have to follow your advice. Why are you setting the dct = None to begin with? What would wrapper return if the dct is not None? Can you please elaborate on the purpose of the wrapper? – HR123r Aug 09 '15 at 23:58
  • After seeing your comment in the other answer, I'd wager that you don't need the caching approach at all. Don't worry about understanding it at this stage. You can probably get by with the first solution: in the other function that you need to use the dictionary in, accept the dictionary as an argument. – jme Aug 10 '15 at 01:17