Обработка и передача большой группы переменных в функции \ объекты в Python - PullRequest
2 голосов
/ 09 марта 2012

Мне нужно работать с функциями и объектами, которые принимают большое количество переменных.

В конкретном случае рассмотрим функцию из отдельного модуля, которая принимает 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

и вызов функции (** somedict), где somedict - это словарь, в котором есть ключи и значения всех переменных, которые мне нужно передать в функцию (и, возможно, некоторые другие). Но я получаю ошибку о неопределенных глобальных переменных.

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

Запуск функции берет список параметров и генерирует объекты моделирования, каждый из которых принимает некоторые параметры в качестве своих атрибутов.

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        

Ответы [ 3 ]

7 голосов
/ 09 марта 2012

Самое чистое решение - вообще не использовать столько параметров в функции.

Вы можете использовать методы или свойства set для установки каждой переменной отдельно, сохраняя их как члены класса и используя функции внутри этого класса.

Эти функции заполняют приватные переменные, и методы get могут использоваться для извлечения этих переменных.

Альтернативой является использование структур (или классов без функций), и таким образом создается именованная группа переменных.

1 голос
/ 09 марта 2012

Вы также можете сгруппировать параметры в кортежи, чтобы создать структуру.

Это не так элегантно, как использование структур или методов get / set, но в большинстве случаев их можно легко применять в существующих приложениях без особых переделок.

Конечно, только связанные параметры должны быть сгруппированы в кортеж.

например. Вы могли бы передать функцию как

value = function_call ((car_model, car_type), возраст, (имя-владельца, адрес-владельца, владелец-телефон))

Это не уменьшает количество параметров, но добавляет немного больше структуры.

1 голос
/ 09 марта 2012

Размещение * args и / или ** kwargs в качестве последних элементов в списке аргументов определения вашей функции позволяет этой функции принимать произвольное число аргументов анонимного и / или ключевого слова.

Вы будете использовать * args, если не уверены, сколько аргументов может быть передано вашей функции.

...