【问题标题】:How to pass to a function a dictionary whose values are lists如何将值是列表的字典传递给函数
【发布时间】:2017-08-24 18:34:41
【问题描述】:

我有一个参数列表,例如:

import numpy as np

param1 = np.arange(0., 1., 0.01)
param2 = np.arange(10., 8000., 100.)
...

我还有一个函数 foo 定义了一个关键字参数列表 arg1, arg2, ... 及其默认值:

def foo(arg1=default1, arg2=default2, ...)

我需要做的是调用这个函数,用我的参数列表中的参数和值(一个一个)更改其中一个默认值,如下所示:

foo(arg1=param1[0])
foo(arg1=param1[1])
...
foo(arg2=param2[0])
foo(arg2=param2[0])

我想到的最好方法是创建一个包含所有参数的字典,然后遍历键和值并从中创建一个新的临时字典,然后调用函数:

all_params = {'arg1':param1, 'arg2':param2, ...}
for key, value_list in all_params.items():
    for value in value_list:
        tmp_dict = {key:value}
        foo(**tmp_dict)

但我有一种感觉,1) 我正在以非 Python 的方式进行迭代,2) 显然有更好的方法来解决这个问题。

编辑:根据@Sebastian 的建议简化了嵌套循环。

【问题讨论】:

    标签: python function numpy dictionary


    【解决方案1】:

    这在我看来是比较简单的。

    def foo(a=0, b=0, c=0):
        return a * b + c
    
    args1 = [1, 2]
    args2 = [3, 4, 5]
    args3 = [6, 7]
    
    args = [args1, args2, args3]
    
    d = {}
    for n, a in enumerate(args):  # Enumerate through all of the parameters.
        for val in a:  # For each parameter, iterate through all of the desired arguments.
            a = [0, 0, 0]  # default_args
            a[n] = val  # Insert the relavent argument into the correct parameter location.
            d[tuple(a)] = foo(*a)  # Call the function and unpack all of the arguments.
    
    # This dictionary holds the function arguments as keys the returned values for those arguments.
    >>> d
    {(0, 0, 6): 6,
     (0, 0, 7): 7,
     (0, 3, 0): 0,
     (0, 4, 0): 0,
     (0, 5, 0): 0,
     (1, 0, 0): 0,
     (2, 0, 0): 0}
    

    【讨论】:

    • OP 明确表示他想每次调用更改一个关键字参数
    • 我会取消投票但仍然认为这是一个错误的答案 a) OP 从未提到他需要访问结果 b) 该解决方案并不比 OP 的解决方案更优雅 c) 使用deepcopy 这肯定不是更有效 d)我们必须强迫自己使用位置参数是不合理的
    【解决方案2】:

    1) 我正在以非 Python 的方式进行迭代

    “Pythonic”是主观的。

    2) 显然有更好的方法来解决这个问题 问题。

    不是这样,考虑到您必须按关键字传递它们并且您必须一次传递一个,您当前正在做的是唯一可能的情况。


    作为一种改进,您可以考虑同时传递所有参数。

    MVCE:

    首先,定义你的函数和字典:

    In [687]: def foo(a, b, c):
         ...:     print(a, b, c)
         ...:  
    
    In [688]: dict_ = {'a': [1, 2, 3], 'b' : [4, 5, 6], 'c' : [7, 8, 9]}
    

    转换为 iters 的字典:

    In [689]: dict_ = {k : iter(v) for k, v in dict_.items()}
    

    运行你的循环:

    In [690]: while True:
         ...:     try: 
         ...:         foo(**{k : next(v) for k, v in dict_.items()})
         ...:     except StopIteration: 
         ...:         break
         ...:     
    1 4 7
    2 5 8
    3 6 9
    

    【讨论】:

    • 这很有用!除了它几乎正是我所需要的之外,我现在还学到了一些关于迭代器及其工作方式的新知识(我在 Python 方面不是很有经验)。但是有一个问题:我一次只需要将一个键:值组合传递给我的函数,而不是字典中的所有键:值组合。所以首先我会检查键'a'的所有值并使用'b'和'c'的默认值,然后切换到'b',依此类推。我该怎么做呢?
    • @MarkoF 在尝试解决您的问题时,我注意到您做了完全相同的事情。因此,您现有的解决方案已经很好了。
    • @MarkoF 还有一件事。请记住,pythonic 是主观的。 :-)
    • 谢谢!很高兴知道我并没有完全浪费一个半小时来尝试解决这个问题。 :-) 我也尝试过使用列表理解来实现这一点,但只是迷失在其中并放弃了,回到了良好的旧嵌套循环。不过,您的迭代器方法确实很有用,我会记住的。
    • @MarkoF 当您必须将来自不同列表的多个参数一起传递时,这很好。但是,当一次传递 1 个参数时,它没有多大意义,这就是为什么我重申你正在做的事情非常好。干杯。
    【解决方案3】:

    你可以稍微简化一下迭代,这样你就不需要再访问all_params[key]了,像这样:

    for key, param in all_params.items():
        for value in param:
    

    【讨论】:

      猜你喜欢
      • 2019-12-12
      • 2014-09-26
      • 1970-01-01
      • 2015-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-23
      • 1970-01-01
      相关资源
      最近更新 更多