2016-08-13 25 views
4

在Python 3也能夠解釋經由memoryview.cast()底層存儲器以字節或整數或多頭的數組:解釋爲bytearray作爲多頭陣列在Python 2.7

[] b=bytearray(2*8) 
[] b 
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') 
[] m=memoryview(b).cast('L') #reinterpret as an array of unsigned longs 
[] m[1]=2**64-1 
[] b 
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff') 

如可以看到的那樣,我們就可以訪問bytearrayb就好像它在一個無符號長整型數組(在我的機器上長8個字節)在memoryviewm的幫助下。

但是,在Python 2.7中的memoryviewlacks方法cast

因此,我的問題是否有可能在Python 2.7中重新解釋一個bytearray作爲一個long數組?

重要的是不要複製/分配更多的內存。

需要的時間在我的機器上讀通過T[i]長值(Python的3.4):

python list:    40ns (fastest but needs 24 bytes per element) 
python array:    120ns (has to create python int-object) 
memoryview of bytearray 120ns (the same as array.array) 
Jean-François's solution: 6630ns (ca. 50 times slower) 
Ross's solution:   120ns 

回答

1

您可以使用ctypes的及其from_buffer方法來創建無符號多頭的一個ctypes陣列與bytearray對象共享內存。

例如:

import ctypes 

ba = bytearray(b'\x00' * 16) 
a = (ctypes.c_ulong * (len(ba)/8)).from_buffer(ba) 
a[1] = -1 
print repr(ba) 
1

不是真的,因爲它重新解釋創建一個副本。在這種情況下,你將不得不

  • 轉換bytearray到多頭的列表
  • 與多頭
  • 轉換回bytearray當你完成

列表工作(有點如將str字符轉換爲字符列表時進行修改,然後將它們加回到字符串中)

import struct 

b=bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff') 

larray=[] 

for i in range(0,len(b),8): 
    larray.append(struct.unpack('@q',b[i:i+8])[0]) 

print(larray) 

larray[1]=1000 

b = bytearray() 

for l in larray: 
    b += struct.pack('@q',l) 

print(b) 

方法,它不涉及副本(只適用於長整型):

def set_long(array,index,value): 
    index *= 8 

    if sys.byteorder=="little": 
     shift=0 
     for i in range(index,index+8): 
      array[i] = (value>>shift) & 0xFF 
      shift += 8 
    else: # sys.byteorder=="big" 
     shift = 56 
     for i in range(index+8,index,-1): 
      array[i] = (value<<shift) & 0xFF 
      shift -= 8 

def get_long(array,index): 
    index *= 8 
    value = 0 

    if sys.byteorder=="little": 
     shift=0 
     for i in range(index,index+8): 
      c = (array[i]<<shift) 
      value += c 
      shift += 8 
    else: # sys.byteorder=="big" 
     shift = 56 
     for i in range(index+8,index,-1): 
      value += (array[i]>>shift) 
      shift -= 8 

    return value 

b=bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff')  
print(get_long(b,1)==2**64-1) 
set_long(b,1,2001) 
print(b) 

print(get_long(b,1)) 

輸出:

bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x03\x00\x00\x00\x00\x00\x00') 
True 
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\xd1\x07\x00\x00\x00\x00\x00\x00') 
2001 
+0

對不起,我不是我的問題明確不夠,整點是要做到這一點,無需額外的內存。 – ead

+0

不是問題,我暫時放棄了用'pack'玩。我想我以後可以想出一個自定義解決方案。 –

+0

增加了一種方法。不是超級光滑的,但與Python 2 –