我是python的新手。我目前正在将文件内容读入字节数组,如下所示:
self.palette = bytearray(fp.read(paletteSize*4))
除了读取所有数据,我还需要执行以下操作:
palette[0] = fp.read(1)
palette[1] = fp.read(1)
palette[2] = fp.read(1)
fp.read(1) #throw a byte away
palette[3] = fp.read(1)
# etc thru paletteSize * 4 bytes, resulting in a size * 3 array
基本上,我需要丢弃每个第4个字节,并将其余字节打包到大小为3/4的数组中。
在代码中性能最佳和最干净的最佳方法是什么?我知道我可以像上面那样在范围上进行for循环手动进行此操作,但这看起来确实很丑,并且在python中而不是在本机C代码中涉及很多内存副本。
我问的原因:这是micropython,文件可能有点大(4+ KB),因此节省25%意义重大。
剧透警报:我正在读取位图文件的调色板部分,该文件编码为蓝色,绿色,红色,0x00的四个字节元组-每个调色板条目的第4个字节都是无用数据。
答案 0 :(得分:3)
由于已经具有调色板大小,因此可以为它预先分配内存,以节省在向其添加数据时扩展字节数组的开销。使用循环一次读取3个字节,然后执行一次搜索以跳过1个字节:
palette = bytearray(paletteSize * 3)
for i in range(paletteSize):
palette[i * 3: (i + 1) * 3] = fp.read(3)
fp.seek(1, 1)
答案 1 :(得分:1)
所以今天我了解了Python中的切片分配,这是缺少的魔术。谢谢@blhsing:)
我最终得到了这个版本,该版本避免了循环切片分配中的某些数学运算:
self.palette = bytearray(paletteSize * 3)
for i in range(0, paletteSize*3, 3):
self.palette[i : (i + 3)] = fp.read(3)
fp.seek(1, 1)
添加为答案而不是注释,因为stackoverflow注释格式很烂
答案 2 :(得分:0)
使用struct
模块。
s = struct.Struct("BBB")
b = bytearray()
for i in range(paletteSize)
b.extend(s.unpack_from(f.read(4))) # b.extend(f.read(4)[:3]) would also work
您甚至可以将其简化为
s = struct.Struct("BBBx" * paletteSize)
b = bytearray(s.unpack(f.read(paletteSize*4)))
尽管我还没有测试过;我从未使用过像这样大的格式字符串,但从理论上讲,它应该可以工作。