[Warning: this answer gets weird]
Ok...to get a variable created you have to run var_1() somehow; to get values named in-scope (local, since you don't want global)
Returning the vars *does* keep the "id" the same if that's what you're after...you're just installing new 'names' for a value that has not lost all of its references yet (the variable isn't passed; the name switches, even if it's the same in both places)...here's a nice article about names vs. values:
Now...here's a way that's...neat but kindof wrong...if you accept that running a function creates a "local variable scope frame":
That's kindof the function's vars when it ran, but It's also kindof weird.
(I'm only really including this to emphasize "local scope")
Diego's answer is definitely the right one. How ever, you can also look at the concept of nonlocal variable if you are working in python 3. It localises the value of a variable within two functions (suppose A and B) where consider B to be an inner function declared in the statement of A function. If A is declared in the statement of another function, say X, then that nonlocal variable will not influence anything in function X.
var = 3
var = 2
var = 1
Kirk Schafer Indeed... that approach is "cringy" 🤣
Might I propose two less cringy options to consider...
Personally, I like the namedtuple because I prefer using the dot notation over brackets with quotes.