我发现自己需要处理带有大量变量的函数和对象。
对于特定情况,考虑来自分离模块的函数,该函数接受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的所有变量的键和值(可能还有一些)。但我得到一个关于未定义的全局变量的错误。
EDIT1:
我将在稍后发布这段代码,因为我现在不在家或实验室。直到那时我会尝试更好地解释这种情况。
我有一个分子动力学模拟,它需要几十个参数。很少需要迭代参数(例如温度)。为了充分利用四核处理器,我并行运行了不同的迭代。因此,代码以不同迭代的循环开始,并且在每次传递时将该迭代的参数发送到工作池(使用多处理模块)。它类似于:
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获取参数列表并生成模拟对象,每个参数都将一些参数作为其属性。
EDIT2:
这是有问题的功能的一个版本。 **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
答案 0 :(得分:7)
最干净的解决方案是根本不在函数中使用那么多参数。
您可以使用set方法或属性分别设置每个变量,将它们存储为类成员并由该类中的函数使用。
这些函数填充私有变量,get方法可用于检索这些变量。
另一种方法是使用结构(或没有函数的类),这样就可以创建一组命名的变量。
答案 1 :(得分:1)
将* args和/或** kwargs作为函数定义参数列表中的最后一项,允许该函数接受任意数量的匿名和/或关键字参数。
当你不确定可以向你的函数传递多少个参数时,你会使用* args。
答案 2 :(得分:1)
您还可以将元组中的参数分组以构建结构。
这不如使用结构或获取/设置方法那么优雅,但可以在现有应用程序中轻松应用而无需太多返工。
当然,只应将相关参数分组为元组。
E.g。你可以把一个函数传递给
value = function_call((car_model,car_type),年龄,(owner.name,owner.address,owner.telephone))
这不会减少参数数量,但会增加更多结构。