命名itertools.products中的可迭代对象部分

10 投票
2 回答
2025 浏览
提问于 2025-04-17 12:07

我最近在了解 itertools 这个模块,听说它非常强大。我特别对 itertools.product() 感兴趣,因为它可以给我所有输入的组合。

不过,我想知道每个输出是来自哪个输入的可迭代对象。例如,一个简单的标准例子是:

itertools.product([1, 2, 3], [1, 2])

如果用户提供的输入是 [1,2,3] 和 [1, 2],我就不知道它们的顺序,所以得到的结果是

(1, 2)

并没有太大帮助,因为我不知道它们的排列顺序。有没有什么方法可以像这样提供输入:

itertools.product(foo = [1, 2, 3], bar = [1, 2])

然后得到像这样的输出:

output['foo'] = 1
output['bar'] = 2

或者

output.foo = 1
output.bar = 2

2 个回答

5

结果总是按照传入的参数顺序排列的,比如在 (1, 2) 中,1 必须来自 [1,2,3],而 2 必须来自 [1,2]

所以,你的需求可以通过重复使用 itertools.product 来满足:

def named_product(**items):
    names = items.keys()
    vals = items.values()
    for res in itertools.product(*vals):
        yield dict(zip(names, res))
23

使用 itertools.product([1, 2, 3], [1, 2]) 这个代码,你会得到一系列有序的配对,第一个元素来自 [1,2,3],第二个元素来自 [1,2]。这个结果是一定会这样产生的。

如果你想要给这些配对起个名字,可以把结果转换成一个 命名元组。这样的话,你就可以通过 output.foooutput.bar 来访问这些字段。结合KennyTM的想法,使用 **items,可以把这个功能放在一个快速且节省内存的函数里:

from itertools import product, starmap
from collections import namedtuple

def named_product(**items):
    Product = namedtuple('Product', items.keys())
    return starmap(Product, product(*items.values()))

下面是一个示例调用:

>>> for output in named_product(foo=[1,2,3], bar=[1,2]):
        print output

Product(foo=1, bar=1)
Product(foo=1, bar=2)
Product(foo=2, bar=1)
Product(foo=2, bar=2)
Product(foo=3, bar=1)
Product(foo=3, bar=2)

撰写回答