在Python 2.7中将bytearray解释为长数组
在Python 3中,可以通过在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]读
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)