【问题标题】:Execute function on all possible combinations of parameters对所有可能的参数组合执行函数
【发布时间】:2017-07-03 14:08:49
【问题描述】:

我有一组值想作为函数的参数应用:

params = {
    'a': [1, 2, 3],
    'b': [5, 6, 7],
    'x': [None, 'eleven', 'f'],
    # et cetera
}

我想以所有可能的组合运行myfunc(),所以myfunc(a=1, b=5, x=None ...)myfunc(a=2, b=5, x=None ...) ... myfunc(a=3, b=7, x='f' ...)。有什么可以提供帮助的(例如itertools)吗?我考虑过使用itertools.product(),但这并没有保留参数的名称,只是给了我组合的元组。

【问题讨论】:

    标签: python function combinations


    【解决方案1】:

    您可以使用itertools.product 获取所有参数组合:

    >>> import itertools
    >>> for xs in itertools.product([1,2], [5,6], ['eleven', 'f']):
    ...     print(xs)
    ... 
    (1, 5, 'eleven')
    (1, 5, 'f')
    (1, 6, 'eleven')
    (1, 6, 'f')
    (2, 5, 'eleven')
    (2, 5, 'f')
    (2, 6, 'eleven')
    (2, 6, 'f')
    

    使用Argument list unpacking,您可以使用关键字参数的所有组合调用myfunc

    params = {
        'a': [1, 2, 3],
        'b': [5, 6, 7],
        'x': [None, 'eleven', 'f'],
    }
    
    def myfunc(**args):
        print(args)
    
    import itertools
    keys = list(params)
    for values in itertools.product(*map(params.get, keys)):
        myfunc(**dict(zip(keys, values)))
    

    输出:

    {'a': 1, 'x': None, 'b': 5}
    {'a': 1, 'x': None, 'b': 6}
    {'a': 1, 'x': None, 'b': 7}
    {'a': 1, 'x': 'eleven', 'b': 5}
    {'a': 1, 'x': 'eleven', 'b': 6}
    {'a': 1, 'x': 'eleven', 'b': 7}
    {'a': 1, 'x': 'f', 'b': 5}
    ...
    

    【讨论】:

    • 这很整洁!不过,我担心订单被取消,因为 dicts 是无序的(对吗?)。这可能意味着 itertools.product() 返回参数的顺序与您拥有键的顺序不同,这将导致不匹配。
    • @Bluefire、myfunc(a=1, b=2, c=3)myfunc(b=2, c=3, a=1) 都可以。
    • map(params.get, keys) 在这里写params.values() 是一种不必要的冗长方式;保证.keys().values() 将对齐,除非字典被修改。
    • @falsetru 我明白,我担心的是不匹配,您将a 的值传递给b,反之亦然。
    • @Bluefire,我可以像其他答案或 DSM 的评论一样激进(?)。但我不确定它是有保证的还是只是 CPython 的实现细节。
    【解决方案2】:

    .keys.values 的顺序在所有 Python 版本中保证(除非 dict 被更改,此处不会发生),所以这可能有点微不足道:

    from itertools import product
    
    for vals in product(*params.values()):
        myfunc(**dict(zip(params, vals)))
    

    您可以在docs找到保证:

    如果键、值和项目视图在没有干预的情况下被迭代 修改字典,项目的顺序会直接 对应。


    演示

    for vals in product(*params.values()):
        print(dict(zip(params, vals)))
    

    {'a': 1, 'x': None, 'b': 5}
    {'a': 1, 'x': None, 'b': 6}
    {'a': 1, 'x': None, 'b': 7}
    {'a': 1, 'x': 'eleven', 'b': 5}
    {'a': 1, 'x': 'eleven', 'b': 6}
    {'a': 1, 'x': 'eleven', 'b': 7}
    {'a': 1, 'x': 'f', 'b': 5}
    {'a': 1, 'x': 'f', 'b': 6}
    {'a': 1, 'x': 'f', 'b': 7}
    ...
    

    【讨论】:

    • 也许添加一个指向guarantee的链接?
    • @DSM 是的,先生,包括在内。谢谢。
    【解决方案3】:

    我开发了combu,就是那个解决方案。

    1. 安装combu

    pip 安装组合

    1. 使用组合
    # Case 1: Directly call
    import combu
    
    for res, param in combu.execute(myfunc, params):
        print(res, params)
    
    # Case 2: Use class
    from combu import Combu
    
    comb = Combu(myfunc)
    
    for res, param in comb.execute(params):
        print(res, params)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多