对于这样的情况,是否存在避免无意义切片复制的常用习惯用法:
>>> a = bytearray(b'hello')
>>> b = bytearray(b'goodbye, cruel world.')
>>> a.extend(b[14:20])
>>> a
bytearray(b'hello world')
在我看来,创建b[14:20]
切片时会发生不必要的复制。而不是在内存中创建一个新切片以提供给extend
我想说“只使用当前对象的这个范围”。
某些方法可以帮助您使用切片参数,例如count
:
>>> a = bytearray(1000000) # a million zero bytes
>>> a[0:900000].count(b'\x00') # expensive temporary slice
900000
>>> a.count(b'\x00', 0, 900000) # helpful start and end parameters
900000
但很多,例如我的第一个例子中的extend
,没有此功能。
我意识到,对于许多应用程序而言,我所说的将是微优化,所以在任何人问之前 - 是的,我已经描述了我的应用程序,这是值得我担心的事情。
我在下面有一个“解决方案”,但欢迎任何更好的想法。
答案 0 :(得分:5)
创建buffer
对象可以避免复制切片,但对于短切片,只需复制该文件就可以了:
>>> a.extend(buffer(b, 14, 6))
>>> a
bytearray(b'hello world')
这里只有一个由内存组成的副本,但是创建buffer
对象的成本超过了省略。不过对于较大的切片应该更好。我不确定这种方法的整体效率有多大。
请注意,对于Python 3(以及可选的Python 2.7),您需要一个memoryview
对象:
>>> a.extend(memoryview(b)[14:20])
答案 1 :(得分:2)
itertools
有islice
。 islice没有count方法,所以在你希望避免复制切片的其他情况下它很有用。正如你所指出的那样 - 无论如何,count都有一种机制
>>> from itertools import islice
>>> a = bytearray(1000000)
>>> sum(1 for x in islice(a,0,900000) if x==0)
900000
>>> len(filter(b'\x00'.__eq__,islice(a,0,900000)))
900000
>>> a=bytearray(b"hello")
>>> b = bytearray(b'goodbye, cruel world.')
>>> a.extend(islice(b,14,20))
>>> a
bytearray(b'hello world')