Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the pythonic way of saving data between function calls?

The context for me is a single int's worth of info I need to retain between calls to a function which modifies that value. I could use a global, but I know that's discouraged. For now I've used a default argument in the form of a list containing the int and taken advantage of mutability so that changes to the value are retained between calls, like so--

 def increment(val, saved=[0]):
    saved[0] += val
    # do stuff

This function is being attached to a button via tkinter, like so~

button0 = Button(root, text="demo", command=lambda: increment(val))

which means there's no return value I can assign to a local variable outside the function.

How do people normally handle this? I mean, sure, the mutability trick works and all, but what if I needed to access and modify that value from multiple functions?

Can this not be done without setting up a class with static methods and internal attributes, etc?

like image 522
temporary_user_name Avatar asked Mar 10 '23 23:03

temporary_user_name


2 Answers

Use a class. Use an instance member for keeping the state.

class Incrementable:
    def __init__(self, initial_value = 0):
        self.x = initial_value
    def increment(self, val):
        self.x += val
        # do stuff

You can add a __call__ method for simulating a function call (e.g. if you need to be backward-compatible). Whether or not it is a good idea really depends on the context and on your specific use case.

Can this not be done without setting up a class with static methods and internal attributes, etc?

It can, but solutions not involving classes/objects with attributes are not "pythonic". It is so easy to define classes in python (the example above is only 5 simple lines), and it gives you maximal control and flexibility.

Using python's mutable-default-args "weirdness" (I'm not going to call it "a feature") should be considered a hack.

like image 120
shx2 Avatar answered Mar 12 '23 13:03

shx2


If you don't want to set up a class, your only1 other option is a global variable. You can't save it to a local variable because the command runs from within mainloop, not within the local scope in which it was created.

For example:

button0 = Button(root, text="demo", command=lambda: increment_and_save(val))

def increment_and_save(val):
    global saved
    saved = increment(val)

1 not literally true, since you can use all sorts of other ways to persist data, such as a database or a file, but I assume you want an in-memory solution.

like image 20
Bryan Oakley Avatar answered Mar 12 '23 13:03

Bryan Oakley