当创建一个 Python 字节数组(传递一个整数)时,它会创建一个包含那么多字节的字节数组,并将它们全部设置为零。
我想清除字节数组,它可能非常大,迭代它并将内容设置为零这样是很差的。
有没有更好的办法?
(memoryviews 和 bytearrays 在 IMO 中的记录很差)
迄今为止最好的资源(但没有一个能回答我的问题)
http://docs.python.org/dev/library/stdtypes.html#bytes-methods
当创建一个 Python 字节数组(传递一个整数)时,它会创建一个包含那么多字节的字节数组,并将它们全部设置为零。
我想清除字节数组,它可能非常大,迭代它并将内容设置为零这样是很差的。
有没有更好的办法?
(memoryviews 和 bytearrays 在 IMO 中的记录很差)
迄今为止最好的资源(但没有一个能回答我的问题)
http://docs.python.org/dev/library/stdtypes.html#bytes-methods
为什么你会假设重新分配字节数组如此缓慢?它比使用translate
或大字节数组快 10 倍以上!
我正在删除原始字节数组,因此您不必担心暂时使用双倍内存
# For small bytearray reallocation is a tiny bit faster
$ python -m timeit -s "s=bytearray('Hello World')" "s.translate('\0'*256)"
1000000 loops, best of 3: 0.672 usec per loop
$ python -m timeit -s "s=bytearray('Hello World')" "lens=len(s);del s;s=bytearray(lens)"
1000000 loops, best of 3: 0.522 usec per loop
# For large bytearray reallocation is much faster
$ python -m timeit -s "s=bytearray('Hello World'*10000)" "s.translate('\0'*256)"
1000 loops, best of 3: 225 usec per loop
$ python -m timeit -s "s=bytearray('Hello World'*10000)" "lens=len(s);del s;s=bytearray(lens)"
10000 loops, best of 3: 18.5 usec per loop
有一种更好的方法可以s
保持相同的参考。您只需要调用__init__
实例上的方法。
>>> s=bytearray(b"hello world")
>>> id(s)
3074325152L
>>> s.__init__(len(s))
>>> s
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
>>> id(s)
3074325152L
测试时间
$ python -m timeit -s "s=bytearray('Hello World'*10000)" "s.__init__(len(s))"
100000 loops, best of 3: 18.7 usec per loop
我在另一台具有更多 RAM 的计算机上运行了这些千兆字节测试
$ python -m timeit -s "s=bytearray('HelloWorld'*100000000)" "s.__init__(len(s))"
10 loops, best of 3: 454 msec per loop
$ python -m timeit -s "s=bytearray('HelloWorld'*100000000)" "s.translate('\0'*256)"
10 loops, best of 3: 1.43 sec per loop
编辑:这个答案是错误的。s = s.translate('\0'*256)
比 慢s = bytearray(256)
,所以在这里使用没有意义translate
。@gnibbler 提供了更好的解决方案。
字节数组有许多与字符串相同的方法。您可以使用翻译方法:
In [64]: s = bytearray('Hello World')
In [65]: s
Out[65]: bytearray(b'Hello World')
In [66]: import string
In [67]: zero = string.maketrans(buffer(bytearray(range(256))),buffer(bytearray(256)))
In [68]: s.translate(zero)
Out[68]: bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
顺便说一句,Dave Beazley 写了一篇非常有用的 bytearrays 介绍。
或者,稍微修改一下millimoose的答案:
In [72]: s.translate('\0'*256)
Out[72]: bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
In [73]: %timeit s.translate('\0'*256)
1000000 loops, best of 3: 282 ns per loop
In [74]: %timeit s.translate(bytearray(256))
1000000 loops, best of 3: 398 ns per loop
以下是在不更改引用的情况下清除字节数组的几种不同方法(以防其他对象引用它):
使用清除():
>>> a=bytearray(10)
>>> a
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
>>> a.clear()
>>> a
bytearray(b'')
使用切片:
>>> a=bytearray(10)
>>> a[0:10] = []
>>> a
bytearray(b'')
>>> a=bytearray(10)
>>> del a[0:10]
>>> a
bytearray(b'')
使用德尔:
>>> a=bytearray(10)
>>> b=a
>>> del a[0:10]
>>> a
bytearray(b'')
您可以验证如果另一个变量,例如b
,references a
,上述技术都不会破坏这一点。以下a
通过创建一个新的字节数组来重置的技术将打破这一点:
>>> a=bytearray(10)
>>> b=a
>>> b is a
True
>>> a=bytearray(10)
>>> b is a
False
但是,以上所有内容都将数组大小更改为 0。也许您只想将所有项目设为 0,保持大小不变,并保持所有引用有效:
>>> a=bytearray(10)
>>> b=a
>>> b is a
True
>>> a[0:10]=bytearray(10)
>>> b is a
True
因此,使用这种技术,您可以轻松地将数组的任何子部分(实际上是任何可变容器)设为 0。
您需要做的就是重新声明您的字节数组
b = bytearray(LEN_OF_BYTE_ARRAY)