benr
benr

Reputation: 67

Defining variables with key and value from a dictionary in a function?

I have a lot of data coming in dictionaries. My code runs some equations that for clarity have the same names as the dictionary keys. Lets say weight = density * volume where data['density'] is the dictionary entry.

I need a compact way to define all this variables inside the scope of my function without writing too many lines and avoiding writing data['whatever'] on every line of my equations.

I've tried this but does not work on the framework of the function.

for key in data:
    exec("%s = %s" % (key, data[key]))

works fine outside the function

def weights(data):
    #this is what I would like
    for key in data:
        key = data[key]

    W1 = rho1 * V1
    W2 = rho2 * V2
    #where rho and V are values found in the dictionary

For more clarity, I am doing this by hand and taking many lines to do it. The name of the key is the name of the variable as you can see. I would like a compact way of unpacking the dictionary without changing the entry data to the function.

    crossAreaSteel = areas["crossAreaSteel"] * mmSqTOmSq
    crossAreaClad = areas["crossAreaClad"] * mmSqTOmSq
    crossAreaAntiCorr = areas["crossAreaAntiCorr"] * mmSqTOmSq
    crossAreaConcr = areas["crossAreaConcr"] * mmSqTOmSq
    crossAreaMarineGrow = areas["crossAreaMarineGrow"] * mmSqTOmSq
    crossAreaJointAntiCorr = areas["crossAreaJointAntiCorr"] * mmSqTOmSq
    crossAreaJointConcrete = areas["crossAreaJointConcrete"] * mmSqTOmSq
    crossAreaExternalPipe = areas["crossAreaExternalPipe"] * mmSqTOmSq
    crossAreaInternalPipe = areas["crossAreaInternalPipe"] * mmSqTOmSq
    rhoSteel = densities['rhoSteel']
    rhoClad = densities['rhoClad']
    rhoCoat = densities['rhoCoat']

Upvotes: 0

Views: 55

Answers (1)

Ipiano
Ipiano

Reputation: 259

If you know exactly what variables are needed for the function and you can modify how the function is called, you can use the ** operator and keyword arguments to unpack the data when passing it to the function.

def function_of_rhos(rho1, rho2, V1, V2, **kwargs):
    return (rho1 * V1, rho2 * V2)


my_args = {"rho1": 2, "rho2": 3, "V1": 0, "V2": 1}
my_args_with_extras = {
    "rho1": 2,
    "rho2": 3,
    "V1": 0,
    "V2": 1,
    "extra1": 4,
    "extra2": "yes",
}

my_args_with_missing = {"rho1": 2, "rho2": 3, "extra1": 4, "extra2": "yes"}

print(function_of_rhos(**my_args))
print(function_of_rhos(**my_args_with_extras))
print(function_of_rhos(**my_args_with_missing))

Yields

(0, 3)
(0, 3)
Traceback (most recent call last):
  File "./test.py", line 19, in <module>
    print(function_of_rhos(**my_args_with_missing))
TypeError: function_of_rhos() missing 2 required positional arguments: 'V1' and 'V2'

If you want to avoid the exception thrown in the last case, you could define the function to have default values that get used for things missing in the dict

def function_of_rhos(rho1, rho2, V1=3, V2=2, **kwargs):
    return (rho1 * V1, rho2 * V2)

Upvotes: 1

Related Questions