0

The problem:

I have a dictionary of keys and values:

param_dict = {
    'VAR1' : 'abcd', 
    'VAR2' : (1, 1),  
    'VAR3' : 10.0
}

I want to write a function that takes in such a dictionary, and will set each key-value pair as a global variable.

What I have so far:

I have already figured out how to create global variables from my dictionary (as described in a number of answers to this older question). I run into problems only when trying to write my code (shown in the cell below) as a function.

# Set defined values as global variables
for k, v in param_dict.items():
    exec(k + '=v')

You can see that each dictionary key is now the name of a global variable, and each dictionary value is the corresponding value:

print(VAR1) # Prints the value of the global variable VAR1

But I don't know how to accomplish the same thing with a function, since placing all my code within a function will result in the creation of local variables, not global variables.

def make_globals(param_dict):
    # Set defined values as global variables
    for k, v in param_dict.items():
        exec(k + '=v')

make_globals(param_dict=param_dict)

print(VAR1) # Returns a NameError

I know you can set global variables from within a function using global (as shown here and here), but this method requires the name of the variable to be hard-coded into the function itself (at least as far as I can tell). This doesn't work for me since my global variable names can vary and I'm looping through multiple key-value pairs that I want to use as global variables. Is there a way around this?

Rory McGuire
  • 151
  • 9

1 Answers1

1

You can do it this way:

def make_globals(param_dict):
    # Set defined values as global variables
    for k, v in param_dict.items():
        vStr = f'"{v}"' if isinstance(v, str) else f'{v}'
        exec(f'{k}={vStr}', globals())

param_dict = {
    'VAR1' : 'abcd', 
    'VAR2' : (1, 1),  
    'VAR3' : 10.0
}

make_globals(param_dict=param_dict)

print(f'VAR1 is {VAR1}')

for k in param_dict:
    print(f'{k} is in globals()') if k in globals() else print(f'{k} is not in globals()')

Output:

VAR1 is abcd
VAR1 is in globals()
VAR2 is in globals()
VAR3 is in globals()

One key point is to pass globals() as an argument to exec(). I also made some changes to the strings you were passing into exec().

UPDATE:

Here's what the first argument passed to exec() looks like:

VAR1="abcd"
VAR2=(1, 1)
VAR3=10.0
constantstranger
  • 9,176
  • 2
  • 5
  • 19
  • Could you explain the purpose of the `vStr = f'"{v}"' if isinstance(v, str) else f'{v}'` line added to the function? – Rory McGuire Jun 22 '22 at 23:59
  • 1
    I've updated my answer to show what the string passed to `exec()` as its first argument looks like. As you can see, for VAR1 we have `VAR1="abcd"`, which is how you would normally initialize a variable to a string value. The way I got the quotes in was by having the `isinstance()` check to special case the use of quotes if the type of the value in the dictionary is `str`. – constantstranger Jun 23 '22 at 00:03