Interpreting bytearray as an array of longs in Python 2.7

In Python 3, you can interpret base memory as an array of bytes or ints or longs via memoryview.cast():

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

As you can see, we can access bytearray bit as if it had an array of unsigned lengths (8 bytes long on my machine) using memoryview m.

However, in Python 2.7 there is memoryview no method cast.

So my question is: is it possible to rethink a bytearrayas an array of longs in Python 2.7?

It is important to do this without copying / allocating more memory.

The time it takes to read a long value through T[i]on my machine (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 solution: 6630ns  (ca. 50 times slower)
Ross solution:           120ns
+4
2

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 longs
  • .
  • 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)

, ( ints):

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
+1

Source: https://habr.com/ru/post/1651143/


All Articles