使用Pythonic方式每次迭代4个元素

39 投票
5 回答
40279 浏览
提问于 2025-04-16 02:22

可能重复的问题:
在处理列表时,最“Pythonic”的方式是什么?

我正在读取一些PNG格式的数据,每个像素有4个通道。我想要逐个像素地遍历这些数据(也就是说,每4个元素代表1个像素,分别是红色、绿色、蓝色和透明度)。

red_channel = 0
while red_channel < len(raw_png_data):
    green_channel, blue_channel, alpha_channel = red_channel +1, red_channel +2, red_channel +3
    # do something with my 4 channels of pixel data ... raw_png_data[red_channel] etc
    red_channel += 4

这种方法似乎不是很“正确”。有没有更符合Python风格的方法,可以每次处理4个项目,并且将这4个项目拆分开来?

5 个回答

9
from itertools import izip
for r,g,b,a in izip(*[iter(data)]*4):
    ...

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

36
vars = [1, 2, 3, 4, 5, 6, 7, 8]
for a, b, c, d in zip(*[iter(vars)]*4):
    print a, b, c, d

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

42

(Python的itertools库其实应该把所有的配方都做成标准函数……)

你可以使用 grouper 函数:

from itertools import zip_longest
def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return izip_longest(fillvalue=fillvalue, *args)

然后你可以通过以下方式遍历像素:

for r,g,b,a in grouper(4, raw_png_data):
  ....

另外,你也可以使用:

irpd = iter(raw_png_data)
for r,g,b,a in zip(irpd, irpd, irpd, irpd):  # use itertools.izip in Python 2.x
  ....

需要注意的是,如果你要处理的内容长度不是4的倍数,这样做会把最后几个字节切掉。另一方面,grouper 函数使用了 izip_longest,所以多出来的字节会用None来填充。

撰写回答