Python >> Tutoriel Python >  >> Python

Python memoryview() — Apprivoisez cette étrange bête !

Le Python memoryview(arg) la fonction renvoie un memoryview objet de l'argument bytes ou bytearray donné. Cela expose les données internes de l'argument (tampons) pour vous aider à accéder aux données sans copie intermédiaire.

Syntax: memoryview(object)
Arguments object Objet Bytes ou Bytarray pour lequel la memoryview doit être renvoyée
Valeur de retour memoryview Renvoie memoryview du object .

Python memoryview() – Exemples d'utilisation

Apprenez par l'exemple ! Dans ce qui suit, nous allons explorer un exemple de pourquoi et comment utiliser le memoryview() fonction intégrée.

Une utilisation simple de memoryview() est de passer la chaîne d'octets b'hello world' en argument :

>>> view = memoryview(b'hello world')
>>> view
<memory at 0x0000025D2D26B1C8>

L'objet de vue est de type memoryview. Vous pouvez accéder aux Unicodes de chaque lettre par simple indexation :

>>> view[0]
104

Si vous convertissez ce premier nombre Unicode en un caractère en utilisant le str() fonction intégrée, vous voyez qu'elle se rapporte au premier caractère de la chaîne d'octets, c'est-à-dire 'h' .

>>> chr(view[0])
'h'

Python memoryview() — Vidéo

Qu'est-ce qu'une Memoryview en Python ?

La distribution Python standard, cPython , est implémenté à l'aide du langage de programmation C. Si vous créez un objet bytes ou un tableau d'octets en Python, celui-ci sera mappé à un objet en mémoire, un objet C, pas un objet Python. En substance, Python n'est qu'une virtualisation au-dessus de C ! Si vous voulez faire des choses sales comme accéder aux objets en mémoire, vous pouvez utiliser le memoryview objet qui est vraiment une référence au véritable objet C en mémoire, mais qui ressemble à n'importe quel autre objet Python ! Plus précisément, le memoryview expose l'interface du tampon en tant qu'objet Python qui peut ensuite être transmis comme n'importe quel autre objet.

"Bien que chacun de ces types ait sa propre sémantique, ils partagent la caractéristique commune d'être soutenus par une mémoire tampon éventuellement importante. Il est alors souhaitable, dans certaines situations, d'accéder directement à ce tampon et sans recopie intermédiaire.” — Documents

Lorsque vous utilisez des octets ou des tableaux d'octets en Python, vous souhaitez souvent accéder directement aux données en mémoire. Le memoryview() fonction vous permet de le faire !

Évaluation des performances :dans quelle mesure l'utilisation d'un Memoryview est-elle plus efficace ?

Dans l'expérience suivante, nous voulons répondre à la question de savoir dans quelle mesure l'utilisation d'un objet memoryview est plus efficace lors de la création d'un grand nombre de tranches sur de grandes chaînes d'octets.

  • Si vous n'utilisez pas les vues de mémoire, vous créerez un grand nombre d'objets intermédiaires, en copiant essentiellement les mêmes données encore et encore.
  • Si vous utilisez memoryviews, vous évitez ces copies redondantes.

L'effet peut être très substantiel comme le montre le graphique d'évaluation suivant :

Ce graphique est le résultat de l'exécution du code suivant pour l'évaluation des performances sur mon Win 10, Intel Core i7, 8th Gen ordinateur :

import time

sizes = range(100000, 600000, 100000)


# Without Memoryview
l1 = []
for n in sizes:
    data = b'x' * n
    start = time.time()
    b = data
    while b:
        b = b[1:]
    stop = time.time()
    print(f'bytes {n} {stop-start}')
    l1.append(stop-start)


# With Memoryview
l2 = []
for n in sizes:
    data = b'x' * n
    start = time.time()
    b = memoryview(data)
    while b:
        b = b[1:]
    stop = time.time()
    print(f'memview {n} {stop-start}')
    l2.append(stop-start)


# Plot everything
import matplotlib.pyplot as plt
plt.plot(l1, 'x-', label='Without Memoryview')
plt.plot(l2, 'o--', label='With Memoryview')
plt.xlabel('Size of Bytearray')
plt.ylabel('Time (s)')
plt.legend()
plt.show()

Les résultats numériques sont les suivants :

bytes 100000 0.1532435417175293
bytes 200000 0.47913265228271484
bytes 300000 1.1720850467681885
bytes 400000 2.15946888923645
bytes 500000 3.440741777420044
memview 100000 0.0
memview 200000 0.015674114227294922
memview 300000 0.03777813911437988
memview 400000 0.04686594009399414
memview 500000 0.05336737632751465

Vous pouvez le voir en utilisant un memoryview peut entraîner des améliorations drastiques des performances !

Quand doit-on utiliser un Memoryview ?

L'exemple précédent a montré qu'un memoryview est plus efficace à bien des égards si vous utilisez le découpage sur de grands bytearrays. En effet, une memoryview est un tableau NumPy généralisé :

"Une vue mémoire est essentiellement une structure de tableau NumPy généralisée en Python lui-même (sans les mathématiques). Il vous permet de partager de la mémoire entre des structures de données (des éléments tels que des images PIL, des bases de données SQLlite, des tableaux NumPy, etc.) sans copie préalable. Ceci est très important pour les grands ensembles de données. Avec lui, vous pouvez faire des choses comme mapper la mémoire sur un très gros fichier, découper un morceau de ce fichier et faire des calculs sur ce morceau (plus facile si vous utilisez NumPy)." (source)


Mais avant de continuer, je suis ravi de vous présenter mon nouveau livre Python Python One-Liners (Lien Amazon).

Si vous aimez les one-liners, vous allez adorer le livre. Il vous apprendra tout ce qu'il y a à savoir sur une seule ligne de code Python. Mais c'est aussi une introduction à l'informatique , science des données, apprentissage automatique et algorithmes. L'univers en une seule ligne de Python !

Le livre est sorti en 2020 avec l'éditeur de livres de programmation de classe mondiale NoStarch Press (San Francisco).

Lien :https://nostarch.com/pythononeliners


Résumé

Le Python memoryview(arg) la fonction renvoie un memoryview objet de l'argument bytes ou bytearray donné.

Cela expose les données internes de l'argument (tampons) pour vous aider à accéder aux données sans copie intermédiaire.

>>> x = memoryview(b'42')
>>> x[0]
52
>>> x[1]
50
>>> x[2]
Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    x[2]
IndexError: index out of bounds on dimension 1

J'espère que vous avez apprécié l'article! Pour améliorer votre formation Python, vous pouvez rejoindre la populaire et gratuite Finxter Email Academy :

Voulez-vous améliorer vos compétences Python d'une manière amusante et facile à consommer ? Considérez les ressources suivantes et devenez un maître codeur !


Post précédent
Prochain article