2012-08-09 17 views
23

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 

क्या कोई स्मृति या गति अंतर है? प्रत्येक का पसंदीदा उपयोग केस क्या है?

उत्तर

12

bytearray पायथन 2.x के string प्रकार का उत्तराधिकारी है। यह मूल रूप से अंतर्निहित बाइट सरणी प्रकार है। मूल string प्रकार के विपरीत, यह उत्परिवर्तनीय है।

दूसरी ओर, array मॉड्यूल, बाहरी दुनिया के साथ संवाद करने के लिए बाइनरी डेटा संरचनाओं को बनाने के लिए बनाया गया था (उदाहरण के लिए, बाइनरी फ़ाइल प्रारूपों को पढ़ने/लिखने के लिए)।

bytearray के विपरीत, यह सभी प्रकार के सरणी तत्वों का समर्थन करता है। यह लचीला है।

तो यदि आपको केवल बाइट्स की एक सरणी की आवश्यकता है, तो bytearray ठीक काम करना चाहिए। यदि आपको लचीली प्रारूपों की आवश्यकता है (कहें कि सरणी के तत्व प्रकार को रनटाइम पर निर्धारित करने की आवश्यकता है), array.array आपका मित्र है।

कोड को देखे बिना, मेरा अनुमान होगा कि bytearray शायद तेज़ है क्योंकि इसे विभिन्न तत्व प्रकारों पर विचार नहीं करना है। लेकिन यह संभव है कि array('B')bytearray लौटाता है।

+10

मैं वास्तव में कहेंगे 'bytes' पायथन 2.x के' str' के उत्तराधिकारी, नहीं 'bytearray' है। –

+0

यह वास्तव में सटीक नहीं है। पायथन 2.x का 'str' पायथन 3.x के स्ट्र और बाइट्स के मिश्रण की तरह है। – Broseph

+1

@Broseph: ठीक है, 'बाइट्स * * * 2.x के' str' के उत्तराधिकारी "बाइट्स के अविभाजित अनुक्रम" को लक्षित करने वाला उत्तराधिकारी है ... – SamB

6

bytearray में सभी सामान्य str विधियां हैं। आप इसे एक म्यूटेबल str (पायथन 3 में बाइट्स)

के रूप में कर सकते हैं जबकि array.array फ़ाइलों को पढ़ने और लिखने के लिए तैयार है। 'बी' array.array

के लिए सिर्फ एक विशेष मामला है

आप देख सकते हैं वहाँ काफी अंतर प्रत्येक

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

अलावा के dir() को देखकर क्या अन्य सभी को कहा, स्रोत ऐसा लगता है पर देख रहे हैं है जिस तरह से वे संग्रहीत होते हैं वह बहुत समान होता है (दोनों केवल सरणी होते हैं) इसलिए कोई बड़ा अंतर नहीं होना चाहिए। bytearray:

typedef struct { 
    PyObject_VAR_HEAD 
    /* XXX(nnorwitz): should ob_exports be Py_ssize_t? */ 
    int ob_exports; /* how many buffer exports */ 
    Py_ssize_t ob_alloc; /* How many bytes allocated */ 
    char *ob_bytes; 
} PyByteArrayObject; 

और array:

typedef struct arrayobject { 
    PyObject_VAR_HEAD 
    char *ob_item; 
    Py_ssize_t allocated; 
    struct arraydescr *ob_descr; 
    PyObject *weakreflist; /* List of weak references */ 
    int ob_exports; /* Number of exported buffers */ 
} arrayobject; 
+2

यह सरणी नहीं है, यह अंतर्निहित 'सूची' है, के लिए देखो 'arraymodule.c'। – jamylak

+0

आह हाँ अच्छा पकड़ो। इसमें कहीं भी सरणी नहीं मिल सका और किसी ने 'PyListObject' को पहले' सरणी 'के लिए संरचना के रूप में पोस्ट किया था। फिक्स्ड। – SamYonnou

+1

ब्लंट होने के लिए खेद है, लेकिन यह जवाब * कुछ भी नहीं समझाता है *। पृथ्वी पर क्यों इसे स्वीकार कर लिया गया है? –

-1

आप array.array उपयोग करने के लिए अपने आप को मॉड्यूल की जरूरत है लगभग कभी नहीं। यह आमतौर पर struct मॉड्यूल जैसे बाइनरी फ़ाइल प्रारूप या प्रोटोकॉल के लिए बाइनरी डेटा बनाने के लिए उपयोग किया जाता है।

bytearray आमतौर पर, के रूप में अजगर 3 के str() करने का विरोध किया या एन्कोडेड पाठ से निपटने के लिए प्रयोग किया जाता है (उदाहरण के लिए UTF-8, ascii, आदि) अजगर 2 के unicode() जो यूनिकोड पाठ के लिए प्रयोग किया जाता है।

अधिकांश समय, आपको टेक्स्ट से निपटने के दौरान स्ट्र (या) का उपयोग करना चाहिए, या जब आपको वस्तुओं के संग्रह की आवश्यकता होती है, तो संख्याओं सहित।

+3

क्षमा करें, यह एक @Lie है। array.array हमेशा उपयोगी होता है जब भी आपको डेटा के समूह के स्मृति-कुशल प्रतिनिधित्व की आवश्यकता होती है। – RayLuo

+1

@Iceberg: हाँ, लेकिन अधिकांश समय आप टुपल या सूची, या कभी-कभी numpy का उपयोग करेंगे। शायद ही यह आवश्यक है या 'array.array() 'का उपयोग करने के लिए एक अच्छा विचार है। –

+0

'बाइट्स 'का उपयोग एन्कोडेड टेक्स्ट से निपटने के लिए किया जाता है, जो पाइथन 2 के स्ट्र प्रकार के समान होता है। 'bytearray'' बाइट्स 'का एक परिवर्तनीय संस्करण है। – Antimony

3

Python Patterns - An Optimization Anecdote एक अच्छा पठन है जो 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()

की गति दोगुनी मैं सबसे तेज़ तरीका में विशेष रूप से दिलचस्पी थी कभी कभी है छंटनी के लिए एक चार बाइट स्ट्रिंग में एक आईपी पता पैक करने के लिए। ऐसा लगता है कि str(bytearray(addr)) और न ही array('B', addr).tostring()pack('4B', *addr) की गति के करीब आते हैं।

+0

मुझे विश्वास है कि int में एक आईपी पता पैक करना वास्तव में सॉर्टिंग के लिए भी तेज़ होगा। –

+0

@LieRyan: क्या यह या तो साइन इन मुद्दों में भाग लेने या एकाधिक परिशुद्धता अंकगणित शामिल नहीं होगा, हालांकि? – SamB

1

अपने परीक्षण से, दोनों स्मृति की amostly एक ही आकार के थे, लेकिन 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 
+0

क्या आप अपने परीक्षण वर्कलोड के बारे में थोड़ा और विवरण दे सकते हैं? – SamB

+1

@ एसएएमबी बीटीडब्ल्यू, क्या आप रोबोट हैं? – salmon

+0

नहीं, लेकिन मैं समीक्षा कतारों में से एक के माध्यम से जा रहा था - शायद "देर से जवाब" एक। वैसे भी, संख्या निश्चित रूप से अब बहुत अधिक सार्थक है, धन्यवाद। – SamB

संबंधित मुद्दे