【问题标题】:How do I pass lots of variables to and from a function in Python?如何在 Python 中将大量变量传入和传出函数?
【发布时间】:2010-10-29 02:11:30
【问题描述】:

我做科学编程,经常想给用户显示提示和变量对,让他们编辑变量,然后用新变量做计算。我经常这样做,所以我编写了一个 wxPython 类来将此代码移出主程序。您为每个变量设置了一个列表,其中包含变量的类型(字符串、浮点数、整数)、提示符和变量的当前值。然后将所有这些列表放在一个大列表中,我的实用程序会创建一个格式整齐的 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 不允许这样做。

我是否应该将大列表分解成更小的列表,然后再组合成大列表以传入和传出函数?还是只是增加了更多出错的地方?

【问题讨论】:

    标签: python pass-by-reference pass-by-value


    【解决方案1】:
    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];
    

    【讨论】:

    【解决方案2】:

    对我来说,理想的解决方案是使用这样的类:

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

    【讨论】:

      【解决方案3】:

      我想到了两个不错的选择。

      第一种是使用字典将所有变量收集到一个地方:

      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)
      

      在这种情况下,我更喜欢类而不是字典,因为您最终可以为类提供一个定义以使其使用更加清晰,或者提供处理一些打包和解包工作的方法。

      【讨论】:

        【解决方案4】:

        如果我可以通过引用将变量传递给函数,那么用户可以更改或不更改它们,一旦程序从函数返回,我将使用这些值。

        您可以通过传递dict(或为方便语法使用Bunch,请参阅http://code.activestate.com/recipes/52308/)获得与“通过引用传递”大致相同的效果。

        【讨论】:

          【解决方案5】:

          如果您有一组有限的这些情况,您可以为每个情况编写特定的包装函数。每个包装器都将完成构建和解包列表的工作,并将其传递给内部函数。

          【讨论】:

            【解决方案6】:

            最简单的方法是创建一个类。该类将具有属性,而不是处理变量列表。然后,您只需使用该类的单个实例。

            【讨论】:

            • 无法计算我一生中创建的“搜索属性”类的数量。 +1
            • 绝对从一门课开始。然后,您可能会发现一些可以分成多个类的数据,或者可以移动到类中的行为。但是创建参数对象是第一步。
            • 作为在一家做科学软件的公司工作的人,我也认为这是正确的做法。通过传递一大堆变量,您基本上放弃了对问题域进行建模。相反,您可以构建一个类层次结构,在更合乎逻辑的意义上将您的问题体现为对象的集合。 10-30 个变量函数调用是来自学术科学背景的业余程序员的典型标志。
            猜你喜欢
            • 2018-09-24
            • 1970-01-01
            • 2019-06-14
            • 2023-03-14
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多