【问题标题】:Handling and passing large group of variables to functions\objects in python处理大量变量并将其传递给python中的函数\对象
【发布时间】:2012-03-09 09:47:38
【问题描述】:

我发现自己需要处理带有大量变量的函数和对象。

对于特定情况,考虑一个来自分离模块的函数,它接受 N 个不同的变量,然后将它们传递给新实例化的对象:

def Function(Variables): 
    Do something with some of the variables
    object1 = someobject(some of the variables)
    object2 = anotherobject(some of the variables, not necessarily as in object1)

虽然我可以传递一长串变量,但有时我会发现自己对一个函数进行更改,这需要更改它可能调用的其他函数或它可能创建的对象。有时变量列表可能会有所变化。

有没有一种优雅的方式来传递大量变量并保持灵活性?

我尝试通过以下方式使用 kwargs:

def Function(**kwargs):

    Rest of the function

并调用 Function(**somedict),其中 somedict 是一个字典,其中包含我需要传递给 Function(可能还有更多)的所有变量的键和值。但我收到关于未定义全局变量的错误。

编辑1:

我稍后会发布这段代码,因为我现在不在家或实验室。在那之前,我会尽力更好地解释情况。

我有一个分子动力学模拟,它需要几十个参数。很少有参数(例如温度)需要迭代。为了充分利用四核处理器,我并行运行了不同的迭代。因此,代码从不同迭代的循环开始,并在每次传递时将该迭代的参数发送到工作池(使用多处理模块)。它是这样的:

P = mp.pool(number of workers) # If i remember correctly this line 
for iteration in Iterations:
     assign values to parameters
     P.apply_async(run,(list of parameters),callback = some post processing)
P.close()
P.join()

函数run获取参数列表并生成模拟对象,每个模拟对象都将一些参数作为其属性。

编辑2:

这是有问题的函数的一个版本。 **kwargs 包含 'sim'、'lattice' 和 'adatom' 所需的所有参数。

def run(**kwargs): 
"""'run' runs a single simulation process.
j is the index number of the simulation run.
The code generates an independent random seed for the initial conditios."""
scipy.random.seed()
sim = MDF.Simulation(tstep, temp, time, writeout, boundaryxy, boundaryz, relax, insert, lat,savetemp)
lattice = MDF.Lattice(tstep, temp, time, writeout, boundaryxy, boundaryz, relax, insert, lat, kb, ks, kbs, a, p, q, massL, randinit, initvel, parangle,scaletemp,savetemp,freeze)
adatom = MDF.Adatom(tstep, temp, time, writeout, boundaryxy, boundaryz, relax, insert, lat, ra, massa, amorse, bmorse, r0, z0, name, lattice, samplerate,savetemp,adatomrelax)                

bad = 1 
print 'Starting simulation run number %g\nrun' % (j+1)    
while bad is 1:
    # If the simulation did not complete successfuly, run it again.
    bad = sim.timeloop(lattice,adatom1,j)
print 'Starting post processing'
# Return the temperature and adatomś trajectory and velocity
List = [j,lattice.temp , adatom1.traj ,adatom1.velocity, lattice.Toptemp,     lattice.Bottomtemp, lattice.middletemp, lattice.latticetop]
return  List        

【问题讨论】:

  • 你在正确的轨道上,使用 *args 或 **kwargs,所以你的代码可能有问题。请张贴出来,让我们看看发生了什么。

标签: python argument-passing


【解决方案1】:

最干净的解决方案是根本不在函数中使用那么多参数。

您可以使用 set 方法或属性来分别设置每个变量,将它们存储为类成员并供该类中的函数使用。

这些函数填充私有变量,get 方法可用于检索这些变量。

另一种方法是使用结构(或没有函数的类),这样可以创建一组命名的变量。

【讨论】:

  • 长参数列表是“代码异味”或反模式,并且有解决它们的文档化解决方案(通常涉及结构或类)。
【解决方案2】:

将 *args 和/或 **kwargs 作为函数定义参数列表中的最后一项允许该函数接受任意数量的匿名和/或关键字参数。

当你不确定有多少参数可以传递给你的函数时,你可以使用 *args。

【讨论】:

    【解决方案3】:

    您还可以将元组中的参数分组以构成结构。

    这不像使用结构或 get/set 方法那样优雅,但可以在现有应用程序中轻松应用,无需太多返工。

    当然只有相关的参数才应该被分组到一个元组中。

    例如你可以有一个函数作为

    value = function_call((car_model, car_type), age, (owner.name, owner.address, owner.telephone))

    这并没有减少参数的数量,而是增加了一点结构。

    【讨论】:

      猜你喜欢
      • 2021-02-28
      • 1970-01-01
      • 1970-01-01
      • 2017-06-10
      • 2017-06-27
      • 2015-07-02
      • 1970-01-01
      • 2014-10-04
      • 1970-01-01
      相关资源
      最近更新 更多