簡體   English   中英

如何將 **kwargs 傳遞給另一個更改了該鍵值的函數?

[英]How to pass **kwargs to another function with changed values for that key?

我有以下函數來計算激光束在腔中的傳播。 它取決於存儲在名為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

如果我想更改參數並查看其對激光的影響,我可以調用該函數,例如

P0 = propagate(1000, core_data, L1=1.2, M5=17)

這非常有效。

現在,我將編寫一個函數,將該函數傳遞給ProcessPoolExecutor ,並使用相同的鍵迭代**ddata的值。 例如,它應該像這樣工作(更簡單的例子):

propagate_parallel(1000, core_data,
                   L1=np.linspace(1, 2, 2),
                   M5=np.linspace(16, 17, 2))

然后應該並行執行此操作:

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)

這樣的事情適用於我的情況:

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))

問題是這不靈活,我不能把它變成一個很好的函數,如上所述。 它應該是一個可以這樣調用的函數來重現上面的代碼:

propagate_parallel(1000, core_data, gdd_dm=xrng, dwl_filt=yrng)

我如何將**ddata的鍵與相應鍵的迭代值一起傳遞?

僅供參考,我用過:

import numpy as np
import concurrent.futures as confu
import itertools as it

您正在尋找迭代笛卡爾積。

這是一種迭代笛卡爾的方法。

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)

這可以適應您的代碼,如果您真的需要並行(這意味着在內核之間的信息拆分方面),請查看 Dask。

希望這足以讓你前進。

編輯:您的問題實際上很難確定。 您的問題真的是如何實現簡單的“函數調用”嗎? 我想一個答案就是制作一個包裝功能,比如......

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)

我想我以某種方式被阻止了......我一直在想如何保留變量名(例如L1 )並將其作為變量傳遞給另一個函數。

@ahead87:你的第一句話已經讓我暢通無阻,我意識到**data可以簡單地通過字典處理。 所以,最后,我只需要將輸入 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

最后,我想我終於明白**kwargs ,它可以作為一個 dict 處理。 謝謝!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM