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

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

学习是最好的投资!

répondre à tous(1)
小葫芦

Tout récemment, j'ai utilisé memoryview pour répondre à cette question.

Bytearray est une séquence d'octets mutable, par rapport à str dans Python2, mais str est immuable.
En Python3, puisque str est un codage Unicode par défaut, il n'est accessible que par octets via bytearray.

Memoryview fournit une interface d'accès à la mémoire octet par octet pour les objets prenant en charge le protocole tampon[1,2]. L'avantage est qu'il n'y a pas de copie mémoire.
Le protocole par défaut str et bytearray prend en charge le tampon tampon.
Comparaison des deux comportements suivants :
Pour faire simple, l'opération de découpage de str et bytearray générera de nouvelles tranches str et bytearray et copiera les données, mais cela n'arrivera pas après l'utilisation de memoryview.

  1. Ne pas utiliser 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. Utiliser la vue mémoire

    >> 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'
    

Mon scénario d'utilisation est la réception de sockets et l'analyse de données dans les programmes réseau :

  1. Le code de réception de la sock avant d'utiliser memoryview est simplifié comme suit

    def read(size):

    ret = '' 
    remain = size
    while True:
        data = sock.recv(remain)
        ret += data     # 这里不断会有新的str对象产生
        if len(data) == remain:
            break
        remain -= len(data)
    return ret
    
  2. Après avoir utilisé meoryview, vous évitez l'épissage constant des chaînes et la génération de nouveaux objets

    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
    

    Le renvoi de memoryview présente également l'avantage de pouvoir recevoir directement l'objet memoryview lors de l'utilisation de struct pour l'analyse de décompression, ce qui est très efficace (évitant un grand nombre d'opérations de découpage lorsqu'une grande str est analysée en segments).

Par exemple :

    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/...

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal