Reputation: 2130
Say for example I have 100 unique functions (for demonstrative purposes I'll just have one)
def calcs(x):
return x**2
and these one hundred unique functions are stored in a list or a dictionary (open to suggestions on ways to store these functions)
import numpy as np
store_funcs = []
for i in np.arange(100):
store_funcs.append(calcs)
now I have an array of 100 numbers
nums = np.random.uniform(0,1, 100)
I would like to pass the first element of nums
to the first function in store_funcs
and have it return the answer, the second element of nums
to the second function in store_funcs
etc... My question is, is there a cleaner (and faster?) way to accomplish this without a loop?
for i in np.arange(100):
print store_funcs[i](nums[i])
Also open to other ideas on how to accomplish this. Thanks!
Upvotes: 0
Views: 59
Reputation: 9633
It looks like your problem could benefit from some parallelism, via the multiprocessing module:
import multiprocessing as mp
# create a function that will execute our function + argument pair
def executor(*args):
# assume args[0] is our function object and args[1] is the number
return args[0](args[1])
# assume we have a list of functions called "funcs" and a list of numbers
# called "nums", and they are of equal length - use zip to pair them off
pairs = zip(funcs, nums)
# create a multiprocessing pool
pool = mp.Pool()
# submit our list of function+argument pairs to the pool for execution
result_list = pool.map(executor, pairs)
# clean up
pool.join()
pool.close()
Some useful links:
Multiprocessing Pools
The zip builtin
It's difficult to answer your original question of which data structure makes more sense, since we don't know how your actual functions and number arrays are generated (I assume [and hope] that they're not all hard-coded) or reused. If what you've described here is really the only use case for both, then the dictionary may make more sense, as it clearly expresses the 1:1 relationship between each function and number.
However, both dictionaries and lists will be equally capable of allowing you to execute the function+argument pairs in an iterative fashion, so if either the list of functions or the array of numbers is reused elsewhere in the code, I would stick with the two lists so their existence as separate entities remains clear.
Upvotes: 1
Reputation: 2032
In general, it's very hard to optimize code without knowing the nature of the code that is being executed. That said, here's a one liner:
map(lambda x : x[0](x[1]), zip(store_funcs, nums))
This probably wouldn't be faster, but it's one line?
On the other hand, if your functions are the bottleneck, then you may want to look into something such as to celery or another async execution library. That way, you would still loop through, but on each iteration, you only spend the time it takes to send a message to some queue for a pool of workers to consume.
Upvotes: 1