在 Python 中传递参数化函数句柄

Posted

技术标签:

【中文标题】在 Python 中传递参数化函数句柄【英文标题】:Passing parameterized function handle in Python 【发布时间】:2016-04-20 05:07:48 【问题描述】:

我有一个通用函数,它定义了我计划使用 scipy.integrate.odeint 集成的 ODE 形式,例如:

def my_ode(K, tau, y, u):
  return K*u/tau - y/tau  # dydt

我的代码中有几个对象,它们都具有my_ode 中定义的动态形式,但具有唯一参数Ktau。我希望能够将一个唯一句柄传递给my_ode,并且在我初始化我的对象时已经设置了这些参数,这样当我更新我的对象时,我所要做的就是在一段时间内模拟soln = odeint(my_ode, t, y, u) t.

例如,如果我定义一个类:

class MyThing:
  def __init__(self, ode, y0):
    # I would rather not maintain K and tau in the objects, I just want the ODE with unique parameters here.
    self.ode = ode
    self.y = y0
    self.time = 0.0

  def update(self, t, u):
    # I want this to look something like:
    self.y = scipy.integrate.odeint(self.ode, t, self.y, u)

当我初始化MyThing 的实例以在初始化时基本上分配参数Ktau 并且永远不需要再次传递它们时,我可以对 Lambdas 做些什么吗?我有点卡住了。

【问题讨论】:

也许你应该看看functools模块的partial函数,它可能对你有用。 我可以只用thing = MyThing(lambda t, y, u: my_ode(K1, tau1, t, y, u), y0) 初始化我的对象,在初始化时为K1tau1 提供值吗?这些价值观会持续存在吗?我还没有到可以在我的代码中测试它的地方。 【参考方案1】:

如果你有:

def my_ode(K, tau, y, u):
    return K*u/tau - y/tau

你可以定义如下:

def make_ode_helper(k, tau): 
    return lambda (y, u): my_ode(K, tau, y, u)

并且应该能够使用以下方法初始化 MyThing:

mt = new MyThing(make_ode_helper(k, tau), y0)

那么你可以只用 y 和 u 参数调用这个助手:

someresult = ode_helper(y, u)

【讨论】:

我可以像您的示例中所示那样调用self.ode(y, u),因为make_ode_helper 返回的lambda 函数将分配给我的类的这个属性吗?如果是这样,我想这就是我正在寻找的东西! 很有可能,试一试。【参考方案2】:

使用 lambda 的解决方案

看起来我可以在初始化对象时使用 lambdas 生成唯一的函数句柄来完成这项工作。为了与odeint 兼容,我需要定义我的函数,以便前两个参数是时间和初始状态:

def my_ode(t, y, u, K, tau):
  return K*u/tau - y/tau  # dydt

接下来我可以使用 lambdas 初始化 MyThing 的对象,将 Ktau 设置为:

thing1 = MyThing(lambda t, y, u: my_ode(t, y, u, 10.0, 0.5), 0.0)

分配给 thing1.ode 的函数句柄现在是 lambda 返回的函数句柄(这可能不是正确的说法),并设置了 Ktau 的值。现在在thing1.update 中,我需要进行一些更改以使其与odeint 一起使用:

def update(self, t_step, t_end, u):
  t_array = np.arange(self.time, t_end, t_step)  # time values at which to evaluate ODE
  response = scipy.integrate.odeint(self.ode, self.y, t_array, (u,))
  self.y = response[-1]  # current state is the last evaluated state

让我有点吃惊的是,任何额外的 ODE 参数都需要作为元组传递给 odeint。这似乎对我想要的效果很好。

还有使用scipy.integrate.ode 的更面向对象的方法,它允许逐步集成功能,非常适合我的模拟目的。为此,我设置了对象的 ODE 并使用以下内容对其进行更新:

class MyThing():
  def __init__(self, ode, y0):
    self.ode = integrate.ode(ode)  # define the ODE
    self.ode.set_integrator("dopri5")  # choose an integrator
    self.ode.set_initial_value(y0)

  def update(self, u, t_step):
    """Update the ODE step-wise."""
    self.ode.set_f_params(u)  # need to pass extra parameters with this method
    self.ode.integrate(self.ode.t + t_step)  # step-wise update
    return self.ode.successful()
  
  def get_output(self):
    """Get output from ODE function."""
    return self.ode.y

【讨论】:

以上是关于在 Python 中传递参数化函数句柄的主要内容,如果未能解决你的问题,请参考以下文章

Python Google BigQuery 参数化 SELECT

使用 map 函数将数组中的值传递给 redshift 参数化查询

Python的函数参数传递

python的参数传递是值传递还是引用传递??

python的参数传递问题!!!

python怎么向类中的函数传递参数