Python:bytearray与数组

时间:2012-08-09 12:00:40

标签: python bytearray

array.array('B')bytearray之间的区别是什么?

from array import array

a = array('B', 'abc')
b = bytearray('abc')

a[0] = 100
b[0] = 'd'

print a
print b

是否存在内存或速度差异?每个用例的首选用例是什么?

6 个答案:

答案 0 :(得分:12)

bytearray是Python 2.x的string类型的继承者。它基本上是内置的字节数组类型。与原始string类型不同,它是可变的。

另一方面,array模块用于创建二进制数据结构以与外界通信(例如,读/写二进制文件格式)。

bytearray不同,它支持所有类型的数组元素。它很灵活。

因此,如果您只需要一个字节数组,bytearray应该可以正常工作。如果您需要灵活的格式(比如需要在运行时确定数组的元素类型),array.array就是您的朋友。

不看代码,我的猜测是bytearray可能更快,因为它不必考虑不同的元素类型。但array('B')可能会返回bytearray

答案 1 :(得分:8)

bytearray拥有所有常用的str方法。你可以把它作为一个可变的str(Python3中的字节)

虽然array.array适合读写文件。 'B'只是array.array的一个特例

您可以看到每个

dir()存在很大差异
>>> dir(bytearray)
['__add__', '__alloc__', '__class__', '__contains__', '__delattr__',
 '__delitem__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
 '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__',
 '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__',
 '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__',
 '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append',
 'capitalize', 'center', 'count', 'decode', 'endswith', 'expandtabs', 'extend',
 'find', 'fromhex', 'index', 'insert', 'isalnum', 'isalpha', 'isdigit', 'islower',
 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans',
 'partition', 'pop', 'remove', 'replace', 'reverse', 'rfind', 'rindex', 'rjust',
 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip',
 'swapcase', 'title', 'translate', 'upper', 'zfill']
>>> dir(array)
['__add__', '__class__', '__contains__', '__copy__', '__deepcopy__',
 '__delattr__', '__delitem__', '__doc__', '__eq__', '__format__', '__ge__',
 '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', 
 '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__',
 '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__',
 '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append',
 'buffer_info', 'byteswap', 'count', 'extend', 'frombytes', 'fromfile',
 'fromlist', 'fromstring', 'fromunicode', 'index', 'insert', 'itemsize', 'pop',
 'remove', 'reverse', 'tobytes', 'tofile', 'tolist', 'tostring', 'tounicode',
 'typecode']

答案 2 :(得分:4)

https://moodle.org/mod/forum/discuss.php?d=115636是一个很好的读物,它指出timing()速度很快。使用该文章中的array.array('B')函数确实显示bytearray()#!/usr/bin/env python from array import array from struct import pack from timeit import timeit from time import clock def timing(f, n, a): start = clock() for i in range(n): f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a); f(a) finish = clock() return '%s\t%f' % (f.__name__, finish - start) def time_array(addr): return array('B', addr) def time_bytearray(addr): return bytearray(addr) def array_tostring(addr): return array('B', addr).tostring() def str_bytearray(addr): return str(bytearray(addr)) def struct_pack(addr): return pack('4B', *addr) if __name__ == '__main__': count = 10000 addr = '192.168.4.2' addr = tuple([int(i) for i in addr.split('.')]) print('\t\ttiming\t\tfunc\t\tno func') print('%s\t%s\t%s' % (timing(time_array, count, addr), timeit('time_array((192,168,4,2))', number=count, setup='from __main__ import time_array'), timeit("array('B', (192,168,4,2))", number=count, setup='from array import array'))) print('%s\t%s\t%s' % (timing(time_bytearray, count, addr), timeit('time_bytearray((192,168,4,2))', number=count, setup='from __main__ import time_bytearray'), timeit('bytearray((192,168,4,2))', number=count))) print('%s\t%s\t%s' % (timing(array_tostring, count, addr), timeit('array_tostring((192,168,4,2))', number=count, setup='from __main__ import array_tostring'), timeit("array('B', (192,168,4,2)).tostring()", number=count, setup='from array import array'))) print('%s\t%s\t%s' % (timing(str_bytearray, count, addr), timeit('str_bytearray((192,168,4,2))', number=count, setup='from __main__ import str_bytearray'), timeit('str(bytearray((192,168,4,2)))', number=count))) print('%s\t%s\t%s' % (timing(struct_pack, count, addr), timeit('struct_pack((192,168,4,2))', number=count, setup='from __main__ import struct_pack'), timeit("pack('4B', *(192,168,4,2))", number=count, setup='from struct import pack'))) 更快:

array.array('B')

实际显示的Python Patterns - An Optimization Anecdote指标bytearray()有时是str(bytearray(addr))的速度的两倍以上

我特别感兴趣的是将IP地址打包成四字节字符串以进行排序的最快方法。看起来array('B', addr).tostring()pack('4B', *addr)都不接近{{1}}的速度。

答案 3 :(得分:2)

从我的测试中,两者都使用了相同大小的内存但是当我创建一个大缓冲区来读取时,bytearry的速度是 1.5倍数组写。

from array import array
from time import time

s = time()

"""
map = array('B')
for i in xrange(256**4/8):
        map.append(0)
"""

#bytearray
map = bytearray()
for i in xrange(256**4/8):
        map.append(0)
print "init:", time() - s

答案 4 :(得分:0)

未提及的一个区别是,对于字节数组和类型为'b'的数组,最终用户字符串表示形式不同。

>>> import array
>>> arr = array.array('b', [104, 105])
>>> byte_arr = bytearray([104, 105])
>>> print(arr)
array('b', [104, 105])
>>> print(byte_arr)
bytearray(b'hi')

这符合bytearray应该是Python3(可变)“原始”字符串类型并假设其数据代表字符的概念。

编辑:

另一个值得注意的区别是,array.array有一个tofile方法可以有效地将数据转储到bytearraybytes缺少的文件中。

答案 5 :(得分:-1)

您几乎不需要自己使用array.array模块。它通常用于创建二进制文件格式或协议的二进制数据,如struct模块。

bytearray通常用于处理编码文本(例如utf-8,ascii等),而不是Python 3的str()或Python 2 unicode()用于Unicode文本。

大多数情况下,你应该在处理文本时使用str(),或者在需要包含数字的项目集合时使用list和tuple。