2016-08-13 11 views
4

でlong型の配列としてのByteArrayを解釈することがmemoryview.cast()介しバイトまたはint型またはlong型の配列として、基礎となるメモリを解釈することが可能である:のPython 3での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のように、memoryviewmの助けを借りて、符号なしlong(私のマシンでは8バイト長)の配列と同じようにアクセスしてください。

しかし、Python 2.7では、memoryviewlacksの方法castです。

私の質問:bytearrayをPython 2.7のlong配列として再解析する可能性はありますか?

さらに多くのメモリをコピー/割り当てせずに行うことが重要です。私のマシン上でT[i]経由long値を読み取るために必要な

時間(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

あなたはその符号なしlong型のctypesの配列を作成するためにctypesとそのfrom_bufferメソッドを使用することができますそのメモリを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に戻って変換
  • long値のリストを
  • 作業(long型のリストにビットを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) 
      

      コピーを伴わない方法(長いだけint型の作品):

      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 –