简体   繁体   English

如何在Python中向函数传递大量变量?

[英]How do I pass lots of variables to and from a function in Python?

I do scientific programming, and often want to show users prompts and variable pairs, let them edit the variables, and then do the calulations with the new variables. 我做科学编程,并且经常想要向用户显示提示和变量对,让他们编辑变量,然后用新变量进行计算。 I do this so often, that I wrote a wxPython class to move this code out of the main program. 我经常这样做,我写了一个wxPython类来将这段代码移出主程序。 You set up a list for each variable with the type of the variable (string, float, int), the prompt, and the variable's current value. 您可以使用变量类型(字符串,浮点数,整数),提示符和变量的当前值为每个变量设置一个列表。 You then place all of these lists in one big list, and my utility creates a neatly formated wxPython panel with prompts and the current values which can be edited. 然后将所有这些列表放在一个大的列表中,我的实用程序创建了一个整齐的wxPython面板,其中包含提示和可以编辑的当前值。

When I started, I only had a few variables, so I would write out each variable. 当我开始时,我只有一些变量,所以我会写出每个变量。

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

Now I want to use this routine for a lot of variables (10-30), and this approach is breaking down. 现在我想将这个例程用于很多变量(10-30),这种方法正在破裂。 I can create the input list to the function over multiple lines using the list.append() statements. 我可以使用list.append()语句通过多行创建函数的输入列表。 When the code returns from the function, though, I get this huge list that needs to be unpacked into the right variables. 但是,当代码从函数返回时,我得到了这个庞大的列表,需要将其解压缩到正确的变量中。 This is difficult to manage, and it looks like it will be easy to get the input list and output list out of sync. 这很难管理,看起来很容易让输入列表和输出列表不同步。 And worse than that, it looks kludgy. 更糟糕的是,它看起来很糟糕。

What is the best way to pass lots of variables to a function in Python with extra information so that they can be edited, and then get the variables back so that I can use them in the rest of the program? 使用额外信息将大量变量传递给Python中的函数的最佳方法是什么,以便可以对它们进行编辑,然后将变量返回以便我可以在程序的其余部分中使用它们?

If I could pass the variables by reference into the function, then users could change them or not, and I would use the values once the program returned from the function. 如果我可以通过引用将变量传递给函数,那么用户可以更改它们,并且一旦程序从函数返回,我将使用这些值。 I would only need to build the input list over multiple lines, and there wouldn't be any possiblity of the input list getting out of sync with the output list. 我只需要在多行上构建输入列表,输入列表就不会与输出列表不同步。 But Python doesn't allow this. 但Python不允许这样做。

Should I break the big lists into smaller lists that then get combined into big lists for passing into and out of the functions? 我是否应该将大型列表拆分为较小的列表,然后将这些列表组合成大型列表以进入和退出函数? Or does this just add more places to make errors? 或者这只是添加更多地方来制造错误?

The simplest thing to do would be to create a class. 最简单的方法是创建一个类。 Instead of dealing with a list of variables, the class will have attributes. 该类将具有属性,而不是处理变量列表。 Then you just use a single instance of the class. 然后你只使用该类的一个实例。

There are two decent options that come to mind. 我想到了两个不错的选择。

The first is to use a dictionary to gather all the variables in one place: 第一种是使用字典在一个地方收集所有变量:

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

The second is to use a class to bundle all the arguments. 第二种是使用类来捆绑所有参数。 This could be something as simple as: 这可能很简单:

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

In this case I would prefer the class over the dictionary, simply because you could eventually provide a definition for the class to make its use clearer or to provide methods that handle some of the packing and unpacking work. 在这种情况下,我更喜欢这个类而不是字典,只是因为你最终可以为类提供一个定义以使其更清晰,或者提供处理一些打包和解包工作的方法。

To me, the ideal solution is to use a class like this: 对我来说,理想的解决方案是使用这样的类:

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

You can also build a dictionary and pass it like this: 您还可以构建一个字典并将其传递给它:

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

You may then get data or alter it as need be when passing it to a function: 然后,您可以在将数据传递给函数时根据需要获取数据或更改数据:

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

If I could pass the variables by reference into the function, then users could change them or not, and I would use the values once the program returned from the function. 如果我可以通过引用将变量传递给函数,那么用户可以更改它们,并且一旦程序从函数返回,我将使用这些值。

You can obtain much the same effect as "pass by reference" by passing a dict (or for syntactic convenience a Bunch , see http://code.activestate.com/recipes/52308/ ). 你可以通过传递一个dict获得与“通过引用传递”相同的效果(或者为了语法方便而获得一个Bunch ,请参阅http://code.activestate.com/recipes/52308/ )。

if you have a finite set of these cases, you could write specific wrapper functions for each one. 如果您有一组有限的这些情况,您可以为每个情况编写特定的包装函数。 Each wrapper would do the work of building and unpacking lists taht are passed to the internal function. 每个包装器都会执行构建和解包列表的工作,这些列表将传递给内部函数。

  1. I would recommend using a dictionary or a class to accumulate all details about your variables 我建议使用字典或类来累积有关变量的所有细节
    • value
    • prompt text 提示文字
  2. A list to store the order in which you want them to be displayed 用于存储您希望它们显示的顺序的列表
  3. Then use good old iteration to prepare input and collect output 然后使用良好的旧迭代来准备输入和收集输出

This way you will only be modifying a small manageable section of the code time and again. 这样,您只需要一次又一次地修改代码的一小部分可管理部分。 Of course you should encapsulate all this into a class if your comfortable working with classes. 当然,如果您习惯使用类,则应将所有这些封装到类中。

"""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 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM