Best way to initialize variable in a module?

Viewed 5174

Let's say I need to write incoming data into a dataset on the cloud. When, where and if I will need the dataset in my code, depends on the data coming in. I only want to get a reference to the dataset once. What is the best way to achieve this?

  1. Initialize as global variable at start and access through global variable

    if __name__="__main__":
        dataset = #get dataset from internet
    

This seems like the simplest way, but initializes the variable even if it is never needed.

  1. Get reference first time the dataset is needed, save in global variable, and access with get_dataset() method

    dataset = None
    
    def get_dataset():
        global dataset
        if dataset is none
            dataset = #get dataset from internet
        return dataset
    
  2. Get reference first time the dataset is needed, save as function attribute, and access with get_dataset() method

    def get_dataset():
        if not hasattr(get_dataset, 'dataset'):
            get_dataset.dataset = #get dataset from internet
        return get_dataset.dataset
    
  3. Any other way

3 Answers

You can also use the lru_cache decorator from the functools module for achieving the goal of running an expensive operation only once.

As long as the parameters are the same, calling the function again and again returns the same object.

https://docs.python.org/3/library/functools.html#functools.lru_cache

@lru_cache
def fun(input1, input2):
    ... # expensive operation
    return result

Similar to MrE's answer, it is best to encapsulate the data with a wrapper.

However, I would recommend you to use a python closure python closure instead of a class.

A class should be used to encapsulate data and relevant functions that are closely related to the data. A class should be something that you will instantiate objects of and objects will retain individuality. You can read more about this here

You can use closures in the following way

def get_dataset_wrapper():
    dataset = None

    def get_dataset():
        nonlocal dataset
        if dataset is none
            dataset = #get dataset from internet
        return dataset
    return get_dataset

You can use this in the following way

dataset = get_dataset_wrapper()()

If the ()() syntax bothers you, you can do this:

def wrapper():
    return get_dataset_wrapper()()
Related