27

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

有内存或速度差异吗?每个人的首选用例是什么?

4

6 回答 6

15

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

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

与 不同bytearray的是,它支持各种数组元素。它很灵活。

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

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

于 2012-08-09T12:06:59.773 回答
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']
于 2012-08-09T12:07:18.470 回答
4

Python Patterns - 优化轶事是一本很好的读物,它指出array.array('B')速度很快。使用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')))

实际显示的timeit度量array.array('B')有时是速度的两倍以上bytearray()

我对将 IP 地址打包成四字节字符串进行排序的最快方法特别感兴趣。看起来既没有str(bytearray(addr))也没有array('B', addr).tostring()接近的速度pack('4B', *addr)

于 2015-07-11T09:15:35.370 回答
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
于 2015-08-11T02:50:42.373 回答
0

尚未提及的一个区别是,最终用户字符串表示对于 bytearrays 和具有 type 的数组是不同的'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')

这符合bytearrayPython3 的(可变)“原始”字符串类型的概念,并假设其数据表示字符。

编辑:

另一个显着的区别是,它array.array有一种tofile方法可以有效地将数据转储到文件bytearraybytes

于 2018-04-10T06:28:52.013 回答
-2

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

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

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

于 2012-08-09T12:18:52.303 回答