1

So let's say I have this function with a lot of variable setting:

def set_variables():
    var_a = 10
    var_b = 200

and these variables need to be set in multiple functions and accessed via their var name. Is there a way to create this function s.t. after it's call the parent function that calls it has var_a and var_b without having to return them? The function above is an example, but in reality there are a lot of variables so it's not really viable to have something like the below.

def parent_function():
   var_a, var_b, ... = set_variables()

ideally I'd like something like

def parent_function():
   set_variables()
   # do some code with var_a or var_b

Or maybe even return a dict of key, val and automatically generate variables of key name set to val.

So for example

def parent_function():
    var_dict = set_variables()
    some_func_to_auto_set_vars_from_dict(var_dict)
    # Do something with var_a or var_b
9
  • 1
    You can create global variables in a function, but you can't create local variables for one function in a separate function, if that is what you are trying to do. Commented Sep 22, 2021 at 20:31
  • 1
    You are looking for dynamically scoped variables: Python is lexically scoped. What you want isn't possible. Commented Sep 22, 2021 at 20:31
  • 2
    If you are willing to have set_variables return a value, just return a single dict instead of multiple values. Commented Sep 22, 2021 at 20:36
  • 4
    This seems like a great time to start learning about object oriented programming. Commented Sep 22, 2021 at 20:51
  • 2
    If you're opposed to OOP, is there any particular reason at least that you don't just use parameters in your function definitions? If set_variables() were to simply return whatever variables necessary, you could then just pass those variables to parent_function(). Commented Sep 22, 2021 at 20:52

2 Answers 2

1

Return a collection that lets you access the values by name without having to re-assign them, e.g. a dict:

def set_variables():
    return {
        'a': 10,
        'b': 200,
    }
def parent_function():
   v = set_variables()
   # do some code with v['a'] or v['b']

Or (my personal preference for this use case) a NamedTuple, which gives you the benefit of type checking (and IDE autocomplete, exactly as if you were using top-level named vars):

from typing import NamedTuple

class Vars(NamedTuple):
    a: int
    b: int

def set_variables() -> Vars:
    return Vars(a=10, b=200)

def parent_function():
    v = set_variables()
    # do some code with v.a and v.b
Sign up to request clarification or add additional context in comments.

3 Comments

is there a way in parent_function to convert the dict to variables named after the key in dict with value val
Use NamedTuple IMO -- expanded answer a bit to show how that works.
Just a heads up, vars is a built-in function that you're shadowing.
0

It may seem easy to let all functions set all variables. But this implicit sharing of state has proven to become a maintenance nightmare.

Rather, use immutable dataclasses; they provide more or less the convenience you request, but allow for much easier reasoning about the code.

@dataclass
class Settings:
  a: str =""
  b: int =5
  ...

def parent():
  s = initialize(Settings(c=[1,2,3]))
  use(s.a, s.b)
  ...

def initialize (s: Settings):
  return dataclass.replace(s,
      b=10, d="@#$_"
    )

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.