在Python 2.7中将bytearray解释为长数组

在Python 2.7中将bytearray解释为长数组,python,python-2.7,bytearray,Python,Python 2.7,Bytearray,在Python 3中,可以通过memoryview.cast()将底层内存解释为字节数组、整数数组或长数组: 如图所示,我们可以访问bytearrayb,就好像在memoryviewm的帮助下,一个无符号长数组(在我的机器上是8字节长)在其中一样 然而,在Python2.7中,memoryview方法cast 因此,我的问题是:在Python2.7中是否有可能将bytearray重新解释为长数组 在不复制/分配更多内存的情况下执行此操作非常重要 在我的机器(Python 3.4)上通过T[i]读

在Python 3中,可以通过
memoryview.cast()将底层内存解释为字节数组、整数数组或长数组:

如图所示,我们可以访问
bytearray
b
,就好像在
memoryview
m
的帮助下,一个无符号长数组(在我的机器上是8字节长)在其中一样

然而,在Python2.7中,
memoryview
方法
cast

因此,我的问题是:在Python2.7中是否有可能将
bytearray
重新解释为长数组

在不复制/分配更多内存的情况下执行此操作非常重要

在我的机器(Python 3.4)上通过
T[i]
读取长值所需的时间:

python列表:40ns(最快,但每个元素需要24字节)
python数组:120ns(必须创建python int对象)
bytearray 120ns的memoryview(与array.array相同)
让·弗朗索瓦的解决方案:6630ns(约慢50倍)
罗斯解:120ns

因为它创建了一个副本,所以不是真正的重新解释。那样的话,你就不得不

  • bytearray
    转换为长列表
  • 使用long列表
  • 完成后,将其转换回bytearray
(有点像在将字符转换为字符列表时使用
str
字符,修改它们,然后将它们重新连接到字符串)

不涉及复制的方法(仅适用于长整数):


您可以使用ctypes及其方法创建一个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)

对不起,我的问题不够明确,关键是在没有额外内存的情况下完成。没问题,我想玩一下
pack
。我想我以后可以想出一个自定义的解决方案。添加了一个方法。虽然不是非常流畅,但可以与python 2tanks一起使用,但我认为您的解决方案比重新解释要慢得多(请参阅我的第二次编辑),但我想这是我必须付出的代价。是的,它的速度非常慢。我希望一些python大师会提出更好的解决方案,但我认为现在人们对python 3的功能更感兴趣,而忘记了python 2。我听说Python 2将在2020年放弃。升级时间:)可能还有另一个解决方案,包括
ctypes
和调用像C这样的本机代码,在这里您可以做任何您想做的事情。
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
import ctypes

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