求解释一下python中bytearray和memoryview 的使用 以及适用的场景
PHPz
PHPz 2017-04-18 10:00:13
0
1
606

x = bytearray(b'abcde')
y = memoryview(x)
y[1:3] = b'yz'
x[1:3] = b'ab'
y[3] = ord(b'e')
x[3] = ord(b'f')

x = bytearray(b'abcde')
while len(x)>0:
x = x[1:]

x = bytearray(b'abcde')
y = memoryview(x)
while len(y)>0:
y = y[1:]

PHPz
PHPz

学习是最好的投资!

membalas semua(1)
小葫芦

Baru-baru ini saya menggunakan memoryview untuk menjawab soalan ini.

Bytearray ialah jujukan bait boleh ubah, berbanding str dalam Python2, tetapi str tidak boleh diubah.
Dalam Python3, memandangkan str ialah pengekodan unikod secara lalai, ia hanya boleh diakses oleh bait melalui bytearray.

Memoryview menyediakan antara muka akses memori bait demi bait untuk objek yang menyokong protokol penimbal[1,2].
Procotol penimbal sokongan str dan bytearray lalai.
Perbandingan dua gelagat berikut:
Ringkasnya, operasi penghirisan str dan bytearray akan menjana kepingan baharu str dan bytearray serta menyalin data, tetapi ia tidak akan berlaku selepas menggunakan memoryview.

  1. Jangan gunakan memoryview

    >> a = 'aaaaaa'
    >> b = a[:2]    # 会产生新的字符串
    
    >> a = bytearray('aaaaaa')
    >> b = a[:2]    # 会产生新的bytearray
    >> b[:2] = 'bb' # 对b的改动不影响a
    >> a
    bytearray(b'aaaaaa')
    >> b
    bytearray(b'bb')
    
  2. Gunakan memoryview

    >> a = 'aaaaaa'
    >> ma = memoryview(a)
    >> ma.readonly  # 只读的memoryview
    True
    >> mb = ma[:2]  # 不会产生新的字符串
    
    >> a = bytearray('aaaaaa')
    >> ma = memoryview(a)
    >> ma.readonly  # 可写的memoryview
    False
    >> mb = ma[:2]      # 不会会产生新的bytearray
    >> mb[:2] = 'bb'    # 对mb的改动就是对ma的改动
    >> mb.tobytes()
    'bb'
    >> ma.tobytes()
    'bbaaaa'
    

Senario penggunaan saya ialah penerimaan soket dan analisis data dalam program rangkaian:

  1. Kod penerimaan stokin sebelum menggunakan memoryview dipermudahkan seperti berikut

    def read(saiz):

    ret = '' 
    remain = size
    while True:
        data = sock.recv(remain)
        ret += data     # 这里不断会有新的str对象产生
        if len(data) == remain:
            break
        remain -= len(data)
    return ret
    
  2. Selepas menggunakan meoryview, anda mengelakkan penyambungan rentetan berterusan dan penjanaan objek baharu

    def read(size):
        ret = memoryview(bytearray(size)) 
        remain = size
        while True:
            data = sock.recv(remain)
            length = len(data)
            ret[size - remain: size - remain + length] = data
            if len(data) == remain:
                break
            remain -= len(data)
        return ret
    

    Mengembalikan memoryview juga mempunyai kelebihan iaitu ia boleh menerima terus objek memoryview apabila menggunakan struct untuk membongkar parsing, yang sangat cekap (mengelakkan sejumlah besar operasi penghirisan apabila str besar dihuraikan dalam segmen).

Contohnya:

    mv = memoryview('\x00\x01\x02\x00\x00\xff...')
    type, len = struct.unpack('!BI', mv[:5])
    ...

[1] https://jakevdp.github.io/blo...
[2] http://legacy.python.org/dev/...

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan