Reputation: 65
I have a list of parameters such as this:
import numpy as np
param1 = np.arange(0., 1., 0.01)
param2 = np.arange(10., 8000., 100.)
...
I also have a function foo
defined with a list of keyword arguments arg1, arg2, ...
and their default values:
def foo(arg1=default1, arg2=default2, ...)
What I need to do is call this function, changing one of those default values (one by one) with the arguments and values from my list of parameters like so:
foo(arg1=param1[0])
foo(arg1=param1[1])
...
foo(arg2=param2[0])
foo(arg2=param2[0])
The best way that I thought of was to create a dictionary of all parameters, and then iterate over keys and values and create a new temporary dictionary out of it and then call the function:
all_params = {'arg1':param1, 'arg2':param2, ...}
for key, value_list in all_params.items():
for value in value_list:
tmp_dict = {key:value}
foo(**tmp_dict)
But I have a feeling that 1) I'm iterating in a non-Pythonic way, 2) and that there is obviously a much better way to solve this problem.
EDIT: streamlined the nested loops a bit according to @Sebastian's suggestion.
Upvotes: 1
Views: 88
Reputation: 109666
This is relatively simple in my opinion.
def foo(a=0, b=0, c=0):
return a * b + c
args1 = [1, 2]
args2 = [3, 4, 5]
args3 = [6, 7]
args = [args1, args2, args3]
d = {}
for n, a in enumerate(args): # Enumerate through all of the parameters.
for val in a: # For each parameter, iterate through all of the desired arguments.
a = [0, 0, 0] # default_args
a[n] = val # Insert the relavent argument into the correct parameter location.
d[tuple(a)] = foo(*a) # Call the function and unpack all of the arguments.
# This dictionary holds the function arguments as keys the returned values for those arguments.
>>> d
{(0, 0, 6): 6,
(0, 0, 7): 7,
(0, 3, 0): 0,
(0, 4, 0): 0,
(0, 5, 0): 0,
(1, 0, 0): 0,
(2, 0, 0): 0}
Upvotes: 1
Reputation: 402872
1) I'm iterating in a non-Pythonic way
"Pythonic" is subjective.
2) That there is obviously a much better way to solve this problem.
Not so, what you're currently doing is the only possible scenario considering you've to pass them by keyword and that you've to pass them one at a time.
As an improvement you might consider passing all your arguments at the same time.
MVCE:
First, define your function and dictionary:
In [687]: def foo(a, b, c):
...: print(a, b, c)
...:
In [688]: dict_ = {'a': [1, 2, 3], 'b' : [4, 5, 6], 'c' : [7, 8, 9]}
Convert to dict of iters:
In [689]: dict_ = {k : iter(v) for k, v in dict_.items()}
Run your loop:
In [690]: while True:
...: try:
...: foo(**{k : next(v) for k, v in dict_.items()})
...: except StopIteration:
...: break
...:
1 4 7
2 5 8
3 6 9
Upvotes: 0
Reputation: 1889
You can simplify the iterating slightly, so that you don't need to access all_params[key]
again, like this:
for key, param in all_params.items():
for value in param:
Upvotes: 0