Как мне передавать множество переменных в функцию и из нее в Python?

StackOverflow https://stackoverflow.com/questions/912526

Вопрос

Я занимаюсь научным программированием и часто хочу показывать пользователям подсказки и пары переменных, позволять им редактировать переменные, а затем выполнять вычисления с новыми переменными.Я делаю это так часто, что написал класс wxPython, чтобы перенести этот код из основной программы.Вы настраиваете список для каждой переменной с указанием типа переменной (string, float, int), запроса и текущего значения переменной.Затем вы помещаете все эти списки в один большой список, и моя утилита создает аккуратно отформатированную панель wxPython с подсказками и текущими значениями, которые можно редактировать.

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

s='this is a string'; i=1; f=3.14
my_list=[ ['s','your string here',s], ['i','your int here',i], ['f','your float here'],]
input_panel = Input(my_list)

 # the rest of the window is created, the input_panel is added to the window, the user is
 # allowed to make  choices, and control returns when the user hits the calculate button

s,i,f = input_panel.results()     # the .results() function returns the values in a list

Теперь я хочу использовать эту процедуру для множества переменных (10-30), и этот подход терпит неудачу.Я могу создать список входных данных для функции в нескольких строках, используя инструкции list.append().Однако, когда код возвращается из функции, я получаю этот огромный список, который необходимо распаковать в нужные переменные.Этим сложно управлять, и, похоже, будет легко рассинхронизировать список ввода и список вывода.И что еще хуже, это выглядит неуклюже.

Каков наилучший способ передать множество переменных в функцию на Python с дополнительной информацией, чтобы их можно было редактировать, а затем получить переменные обратно, чтобы я мог использовать их в остальной части программы?

Если бы я мог передавать переменные по ссылке в функцию, тогда пользователи могли бы изменять их или нет, и я бы использовал значения, как только программа вернется из функции.Мне нужно было бы только создать список входных данных из нескольких строк, и не было бы никакой возможности, чтобы список входных данных не синхронизировался со списком выходных данных.Но Python этого не допускает.

Должен ли я разбивать большие списки на более мелкие списки, которые затем объединяются в большие списки для передачи в функции и выхода из них?Или это просто добавляет больше мест для совершения ошибок?

Это было полезно?

Решение

Самое простое, что можно было бы сделать, - это создать класс.Вместо того чтобы иметь дело со списком переменных, класс будет иметь атрибуты.Затем вы просто используете один экземпляр класса.

Другие советы

Есть два достойных варианта, которые приходят на ум.

Первый - использовать словарь для сбора всех переменных в одном месте:

d = {}
d['var1'] = [1,2,3]
d['var2'] = 'asdf'
foo(d)

Второй способ заключается в использовании класса для объединения всех аргументов.Это может быть что-то столь же простое, как:

class Foo(object):
    pass
f = Foo()
f.var1 = [1,2,3]
f.var2 = 'asdf'
foo(f)

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

На мой взгляд, идеальным решением является использование такого класса, как этот:

>>> class Vars(object):
...     def __init__(self, **argd):
...             self.__dict__.update(argd)
...
>>> x = Vars(x=1, y=2)
>>> x.x
1
>>> x.y
2

Вы также можете создать словарь и передать его следующим образом:

>>> some_dict = {'x' : 1, 'y' : 2}
>>> #the two stars below mean to pass the dict as keyword arguments
>>> x = Vars(**some_dict)  
>>> x.x
1
>>> x.y
2

Затем вы можете получить данные или изменить их по мере необходимости при передаче их в функцию:

>>> def foo(some_vars):
...     some_vars.z = 3 #note that we're creating the member z
...
>>> foo(x)
>>> x.z
3

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

Вы можете получить почти тот же эффект, что и "передача по ссылке", передав dict (или для синтаксического удобства a Bunch, видеть http://code.activestate.com/recipes/52308/).

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

  1. Я бы рекомендовал использовать словарь или класс для накопления всех сведений о ваших переменных
    • значение
    • текст приглашения
  2. Список для хранения порядка, в котором вы хотите, чтобы они отображались
  3. Затем используйте старую добрую итерацию для подготовки входных данных и сбора выходных данных

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

"""Store all variables
"""
vars = {}
"""Store the order of display
"""
order = []

"""Define a function that will store details and order of the variable definitions
"""
def makeVar(parent, order, name, value, prompt):
    parent[name] = dict(zip(('value', 'prompt'), (value, prompt)))
    order.append(name)

"""Create your variable definitions in order
"""
makeVar(vars, order, 's', 'this is a string', 'your string here')
makeVar(vars, order, 'i', 1, 'your int here')
makeVar(vars, order, 'f', 3.14, 'your float here')

"""Use a list comprehension to prepare your input
"""
my_list = [[name, vars[name]['prompt'], vars[name]['value']] for name in order]
input_panel = Input(my_list)

out_list = input_panel.results();
"""Collect your output
"""
for i in range(0, len(order)):
    vars[order[i]]['value'] = out_list[i];
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top