首页 > 解决方案 > 'Bijectively' 将函数列表应用于参数列表

问题描述

比如说,我在代码中定义了一些函数;让我们以两条不同的 PDF 曲线为例:

import numpy as np

# Gaussian 1
def fa(mu, sigsq, x):
    return ((np.sqrt(2*np.pi*sigsq))**(-1) 
            * np.exp((-0.5 * (x - mu + 1)**2)/sigsq))

# Gaussian 2
def fb(nu, omsq,  x):
    return ((np.sqrt(2*np.pi*omsq))**(-1) 
            * np.exp(-(0.5 * (x - nu - 1)**2)/omsq))

...

fs = [fa, fb, ...]

将具有相同数量参数的函数列表应用于某些给定的函数很容易:

fmap = lambda fns, *args: map(lambda fn: fn(*args), fns)

multipeak_gauss = lambda x: sum(list(fmap(fs, 0., 1., x)))

现在让每个函数都有一个唯一的、不同大小的参数集:

import numpy as np

# Gaussian
def fa(mu, sigsq, x):
    return ((np.sqrt(2*np.pi*sigsq))**(-1) 
            * np.exp((-0.5 * (x - mu + 1)**2)/sigsq))

# Maxwell-Boltzmann
def fb(a, x):
    return (np.sqrt(2/np.pi) 
            * (x**2 / a**3) 
            * np.exp(-(x**2)/(2*a**2)))

...

fs  = [fa,           fb,       ...]
ars = [[0., .1, 1.], [1., 1.], ...]

参数列表列表也可以是元组列表或任何此类列表。如何将每组参数一对一地传递给每个函数,而无需重写所有函数以接受列表?

到目前为止我最好的猜测:

specmap = lambda fns, *args: [fn(arg) for fn, arg in zip(fns, *args)]

这段代码遇到了一个明显的问题,即它将一个列表传递给一个只需要普通参数的函数。直觉告诉我,我可以以某种方式进一步“解开”列表列表中的每个列表,例如

specmap = lambda fns, *args: [fn(ar for ar in arg) for fn, arg in zip(fns, *args)]

虽然上面的代码显然功能失调,我不知道它究竟是如何完成的。

标签: pythonlistfunctionnumpylambda

解决方案


正如@hpaulj 在评论中概述的那样,解决方案是“打开”函数内的特定参数列表:

specmap = lambda fns, args: [fn(*arg) for fn, arg in zip(fns, args)]

同时将集合的输入列表保留为列表,而不是 *list 对象。


推荐阅读