簡體   English   中英

Python:bytearray與數組

[英]Python: bytearray vs array

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

有沒有記憶或速度差異? 每個人的首選用例是什么?

bytearray是Python 2.x的string類型的后繼者。 它基本上是內置的字節數組類型。 與原始string類型不同,它是可變的。

另一方面,創建array模塊以創建二進制數據結構以與外界通信(例如,讀/寫二進制文件格式)。

bytearray不同,它支持所有類型的數組元素。 它很靈活。

因此,如果您只需要一個字節數組,則bytearray應該可以正常工作。 如果您需要靈活的格式(比如需要在運行時確定數組的元素類型), array.array就是您的朋友。

不看代碼,我的猜測是bytearray可能更快,因為它不必考慮不同的元素類型。 但是array('B')返回一個bytearray

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']

Python模式 - 優化軼事是一個很好的讀取,指向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)的速度pack('4B', *addr)

從我的測試來看,兩者都使用相同大小的內存,但是當我創建一個大的緩沖區來讀寫時,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

未提及的一個區別是,對於字節數組和類型為'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缺少的文件中。

您幾乎不需要自己使用array.array模塊。 它通常用於創建二進制文件格式或協議的二進制數據,如struct模塊。

bytearray通常用於處理編碼文本(例如utf-8,ascii等),而不是Python 3的str()或用於Unicode文本的Python 2的unicode()

大多數情況下,在處理文本時應該使用str(),或者在需要包含數字的項目集合時使用list和tuple。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM