[英]How to pass **kwargs to another function with changed values for that key?
I have the following function that calculate the propagation of a laser beam in a cavity.我有以下函数来计算激光束在腔中的传播。 It depends on many parameters that are stored in a dict called
core_data
, which is a basic parameter set.它取决于存储在名为
core_data
的字典中的许多参数,这是一个基本参数集。
def propagate(N, core_data, **ddata):
cd = copy.deepcopy(core_data) # use initial configuration
cd.update(ddata) # update with data I want to change
cavity = get_new_cavity(cd) # get new cavity object
P = []
for i in range(N):
cavity.evolve(1)
P.append(cavity.get_power())
return P
If I want to change a parameter and see its effect on the laser, I can just call the function like, for instance如果我想更改参数并查看其对激光的影响,我可以调用该函数,例如
P0 = propagate(1000, core_data, L1=1.2, M5=17)
This works very well.这非常有效。
Now, I would write a function that passes this function to a ProcessPoolExecutor
, with the values of **ddata
being iterated over using the same key.现在,我将编写一个函数,将该函数传递给
ProcessPoolExecutor
,并使用相同的键迭代**ddata
的值。 It should work, for instance, like this (simpler example):例如,它应该像这样工作(更简单的例子):
propagate_parallel(1000, core_data,
L1=np.linspace(1, 2, 2),
M5=np.linspace(16, 17, 2))
And should then do this in parallel:然后应该并行执行此操作:
propagate(1000, core_data, L1=1, M5=16)
propagate(1000, core_data, L1=1, M5=17)
propagate(1000, core_data, L1=2, M5=16)
propagate(1000, core_data, L1=2, M5=17)
Something like this works for my case:这样的事情适用于我的情况:
xrng = np.linspace(110e-30, 150e-30, Nx)
yrng = np.linspace(6.6e-9, 6.7e-9, Ny)
futures = []
with confu.ProcessPoolExecutor(max_workers=Ncores) as pool:
for y, x in it.product(yrng, xrng):
futures.append(pool.submit(propagate, RTs=1000,
core_data=core_data,
gdd_dm=x, dwl_filt=y))
The problem is that this is not flexible and I cannot get this into a nice function, as written above.问题是这不灵活,我不能把它变成一个很好的函数,如上所述。 It should be a function that can be called like this to reproduce the code from above:
它应该是一个可以这样调用的函数来重现上面的代码:
propagate_parallel(1000, core_data, gdd_dm=xrng, dwl_filt=yrng)
How would I pass the keys from **ddata
with the iterated values of that corresponding key?我如何将
**ddata
的键与相应键的迭代值一起传递?
FYI, I used:仅供参考,我用过:
import numpy as np
import concurrent.futures as confu
import itertools as it
You are looking for iterating over the cartesian product.您正在寻找迭代笛卡尔积。
Here is a way to iterate over a cartesian.这是一种迭代笛卡尔的方法。
from itertools import product
import numpy as np
L1=np.linspace(1, 2, 2)
M5=np.linspace(16, 17, 2)
dconf = dict(data=5)
size = L1.size
loop_size = size**2
def propagate(N, data, modifiers):
data.update(modifiers)
out = []
for i in range(N):
out.append('%s : %s : %s : %s'%(i, *data.values()))
return out
mod = (dict(L1=i, M5=j) for i, j in product(L1, M5))
m = map(propagate, np.arange(2, 2+loop_size), (dconf,)*loop_size, mod)
for outer in m:
for inner in outer:
print(inner)
This you can adapt to your code, and if you really need to go parallell (with all that this means in terms of info split between cores) maybe take a look into Dask.这可以适应您的代码,如果您真的需要并行(这意味着在内核之间的信息拆分方面),请查看 Dask。
Hope this is enough to get you going.希望这足以让你前进。
edit: your question is quite hard to actually pinpoint.编辑:您的问题实际上很难确定。 Is your question really how to just achieve the simple "function call"?
您的问题真的是如何实现简单的“函数调用”吗? I suppose one answer is just to make a wrap function, something like...
我想一个答案就是制作一个包装功能,比如......
def propagate(N, data, modifiers):
...
def call_propagate(N, data, L1_, M5_):
mod = ...
m = map(...
return m
for outer in call_propagate(1000, dconf, L1, M5)
for inner in outer:
print(inner)
I think I was somehow blocked... I kept thinking how to keep a variable name (for instannce L1
) and pass this as a variable to another function.我想我以某种方式被阻止了......我一直在想如何保留变量名(例如
L1
)并将其作为变量传递给另一个函数。
@ahead87: Already your first sentence unblocked me and I realized that **data
can be handled simply via a dictionary. @ahead87:你的第一句话已经让我畅通无阻,我意识到
**data
可以简单地通过字典处理。 So, in the end, I simply needed to transform the input dict into a list of dicts for the next function, like so (with some irrelevant parts being snipped):所以,最后,我只需要将输入 dict 转换为下一个函数的 dicts 列表,就像这样(剪掉一些不相关的部分):
def propagate_parallel(RTs, cav_data, **ddata):
keys = list(ddata.keys())
values = list(ddata.values())
futures = []
res = []
with confu.ProcessPoolExecutor(max_workers=32) as pool:
for i in it.product(*values):
futures.append(pool.submit(propagate, RTs=RTs,
cav_data=cav_data,
**dict(zip(keys, list(i)))))
for fut in futures:
res.append(fut)
return res
In the end, I think I finally understand **kwargs
, and that it can be handles as a dict.最后,我想我终于明白
**kwargs
,它可以作为一个 dict 处理。 Thank you!谢谢!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.