可以从左侧截断的Python缓冲区?
现在,我正在使用字符串、StringIO 或 cStringIO 来缓存字节。但是,我经常需要从缓存的左侧删除字节。一个简单的方法是重建整个缓存,但这样做效率不高。如果从左边截断是一个非常常见的操作,有没有更好的方法呢?Python 的垃圾回收器应该会处理被截断的字节。
如果有任何算法可以做到这一点(比如把缓存分成小块),或者有没有现成的实现,那就太好了。
编辑:
我尝试使用 Python 2.7 的 memoryview 来解决这个问题,但遗憾的是,当原始引用被删除时,“视图”之外的数据并不会被垃圾回收:
# (This will use ~2GB of memory, not 50MB)
memoryview # Requires Python 2.7+
smalls = []
for i in xrange(10):
big = memoryview('z'*(200*1000*1000))
small = big[195*1000*1000:]
del big
smalls.append(small)
print '.',
2 个回答
1
你可以把缓冲区当成一个字符或行的列表来构建,然后对这个列表进行切片。只有在输出的时候才把它们连接成字符串。这样做对于大多数需要“可变字符串”功能的情况来说是相当高效的。
垃圾回收机制会清理那些被截断的字节,因为它们在列表中不再被引用。
更新:如果你想修改列表的开头,可以简单地反转这个列表。虽然听起来这样做效率不高,但其实Python的列表实现会在内部进行优化。
来自 http://effbot.org/zone/python-list.htm 的信息:
反转操作很快,所以如果你需要在列表的开头删除和插入很多项目,暂时反转列表通常可以加快速度:
L.reverse() # append/insert/pop/delete at far end L.reverse()
3
如果你经常需要从左边删除元素,使用deque会比较高效。跟用列表、字符串或缓冲区不同,deque在两端删除元素的时间平均是O(1),也就是说速度很快。不过,从内存使用上来说,它会比字符串占用更多空间,因为每个字符都会被当作一个独立的字符串对象来存储,而不是紧凑地放在一起。
另外,你也可以自己实现一个类似的结构,比如用固定大小的字符串或缓冲区对象来做一个链表,这样可能会更节省内存。