The Python Oracle

Avoid global variable in a python util file

--------------------------------------------------
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
and get $2,000 discount on your first invoice
--------------------------------------------------

Music by Eric Matyas
https://www.soundimage.org
Track title: Puzzle Game 5 Looping

--

Chapters
00:00 Avoid Global Variable In A Python Util File
01:09 Accepted Answer Score 4
01:59 Answer 2 Score 3
02:50 Thank you

--

Full question
https://stackoverflow.com/questions/3782...

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python

#avk47



ACCEPTED ANSWER

Score 4


The following is a simple example of a closure. The dictionary, cache, is encapsulated within the outer function (load_func), but remains in scope of the inner, even when it is returned. Notice that load_func returns the inner function as an object, it does not call it.

In utilities.py:

def _load_func(filename):

    cache = {}

    with open(filename) as fn:
        for line in fn:
            key, value = line.split()
            cache[int(key)] = value

    def inner(number):
        return number in cache

    return inner

is_valid = _load_func('valid.txt')

In __main__:

from utilities import is_valid                  # or something similar

if is_valid(42):
    print(42, 'is valid')
else:
    print(42, 'is not valid')

The dictionary (cache) creation could have been done using a dictionary comprehension, but I wanted you to concentrate on the closure.




ANSWER 2

Score 3


The variable valid_dict would not be global but local to utilities.py. It would only become global if you did something like from utilities import *. Now that is considered bad practice when you're developing a package.

However, I have used a trick in cases like this that essentially requires a static variable: Add an argument valid_dict={} to is_valid(). This dictionary will be instantiated only once and each time the function is called the same dict is available in valid_dict.

def is_valid(number, valid_dict={}):
    if not valid_dict:
        # first call to is_valid: load valid.txt into valid_dict
    # do your check

Do NOT assign to valid_dict in the if-clause but only modify it: e.g., by setting keys valid_dict[x] = y or using something like valid_dict.update(z).

(PS: Let me know if this is considered "dirty" or "un-pythonic".)