使用itertools.product

时间:2017-12-15 07:29:03

标签: python

我想使用python来操作大约8个参数的所有组合,评估每个组合对系统的影响。

我在考虑的方法比8个嵌套for循环更好,并且发现了itertools.product。这样可以提供更平坦的结构,但是引用product的结果的好方法是什么?使用嵌套循环组合中的每个参数都有一个方便的名称来引用它。使用itertools方法,我有一些代码来为序列中的参数设置名称。

示例(仅包含3个参数且文件处理不当):

嵌套循环版本

import csv
import itertools

csv_writer = csv.writer(open('data.csv', 'wb'))
csv_writer.writerow(("x", "y", "bpp", "raw_size_bytes", "file_size_bytes"))

# 8bpp and below needs 1 byte per pixel, 9 to 16 bpp needs 2 bytes
file_bytes_per_pixel = [1]*9 + [2]*8

# iterate over parameter combination in nested "for"
for x in [640, 1024, 2048]:
    for y in [320, 1024, 1024]:
        for bpp in [8,10, 16]:
            raw_size_bytes = (x * y * bpp) / 8
            file_size_bytes = x * y * file_bytes_per_pixel[bpp]
            csv_writer.writerow((x, y, bpp, raw_size_bytes, file_size_bytes))

继续进入itertools版本

csv_writer = csv.writer(open('data2.csv', 'wb'))
csv_writer.writerow(("x", "y", "bpp", "raw_size_bytes", "file_size_bytes"))
range_x = [640, 1024, 2048]
range_y = [320, 1024, 1024]
range_bpp = [8,10, 16]

for x, y, bpp in itertools.product(range_x, range_y, range_bpp):
    raw_size_bytes = (x * y * bpp) / 8
    file_size_bytes = x * y * file_bytes_per_pixel[bpp]
    csv_writer.writerow((x, y, bpp, raw_size_bytes, file_size_bytes))

在itertools版本中,我重复四次不同参数的含义

  1. 编写csv文件标题
  2. 设置范围
  3. 将范围传递给product
  4. product
  5. 的结果命名

    使用名称定义的索引

    如果我给参数名称赋予数字,那么可能会有所改进:

    csv_writer = csv.writer(open('data3.csv', 'wb'))
    
    x, y, bpp = range(3)
    params = range(3)
    
    params[x] = [640, 1024, 2048]
    params[y] = [320, 1024, 1024]
    params[bpp] = [8, 10, 16]
    
    csv_writer.writerow(("x", "y", "bpp", "raw_size_bytes", "file_size_bytes"))
    
    for p in itertools.product(*params):
        raw_size_bytes = (p[x] * p[y] * p[bpp]) / 8
        file_size_bytes = p[x] * p[y] * file_bytes_per_pixel[p[bpp]]
        csv_writer.writerow((p[x], p[y], p[bpp], raw_size_bytes, file_size_bytes))
    

    我觉得我只重复自己两次,但每次我提到产品的结果时我都会p[]

    如果我在(有序)词典中有参数,那么我可以使用.keys()来获取名称列表,使用.values()来获取product的范围。但后来我不知道如何将product的结果转化为具有良好名称的变量来进行计算。

    在提出这个问题的过程中,我觉得我已经采取了一种方式来做到这一点,我感到非常满意,但是有一种更清洁的方式来使用产品并且能够推荐以合理的方式从它返回的序列中的各个成员?

2 个答案:

答案 0 :(得分:0)

这感觉有点令人沮丧{{​​3}},但是你可以采用这种方法来减少重复的出现:)

out = ((x, y, bpp, x * y * bpp / 8, x * y * file_bytes_per_pixel[bpp]) for
        x, y, bpp in itertools.product(range_x, range_y, range_bpp))
csv_writer.writerow(out)

我不熟悉编写器,因此您可能需要输出列表而不是生成器。

答案 1 :(得分:0)

在提出这个问题的过程中,我认为我已经回答了这个问题,最简洁的做法似乎是将“产品”与字典一起使用。

csv_writer = csv.writer(open('data3.csv', 'wb'))

x, y, bpp = range(3)
params = range(3)

params[x] = [640, 1024, 2048]
params[y] = [320, 1024, 1024]
params[bpp] = [8, 10, 16]

csv_writer.writerow(("x", "y", "bpp", "raw_size_bytes", "file_size_bytes"))

for p in itertools.product(*params):
    raw_size_bytes = (p[x] * p[y] * p[bpp]) / 8
    file_size_bytes = p[x] * p[y] * file_bytes_per_pixel[p[bpp]]
    csv_writer.writerow((p[x], p[y], p[bpp], raw_size_bytes, file_size_bytes))