Où sont python bytearrays utilisé?
Je suis récemment tombé sur le type de données appelé bytearray
en python. Quelqu'un pourrait-il fournir des scénarios où bytearrays sont nécessaires?
Vous devez vous connecter pour publier un commentaire.
Je suis récemment tombé sur le type de données appelé bytearray
en python. Quelqu'un pourrait-il fournir des scénarios où bytearrays sont nécessaires?
Vous devez vous connecter pour publier un commentaire.
Un
bytearray
est très similaire à un régulière chaîne python (str
en python2.x,bytes
en python3) mais avec une différence importante, alors que les chaînes sont immuable,bytearray
s sont mutables, un peu comme unlist
de simples chaînes de caractères.C'est utile parce que certaines applications utilisent des séquences d'octets dans les moyens qui fonctionne mal avec les cordes immuables. Lorsque vous faites beaucoup de petits changements dans le milieu de gros blocs de mémoire, comme dans un moteur de base de données, ou l'image de la bibliothèque, les chaînes d'effectuer très mal, puisque vous devez faire une copie de l'ensemble (éventuellement, gros) chaîne de caractères.
bytearray
s ont l'avantage de le rendre possible de faire ce genre de changement sans en faire une copie de la mémoire.Mais ce cas particulier, est en fait plus l'exception plutôt que la règle. La plupart des usages impliquent de la comparaison de chaînes, ou de mise en forme de chaîne. Pour ces derniers, il y a généralement une copie de toute façon, une mutable type offrirait aucun avantage, et pour les anciens, depuis les cordes immuables ne peut pas changer, vous pouvez calculer un
hash
de la chaîne et de les comparer comme un raccourci pour la comparaison de chaque octet dans l'ordre, ce qui est presque toujours une grande victoire; et donc c'est l'immuable type (str
oubytes
) qui est la valeur par défaut; etbytearray
est l'exception, quand vous en avez besoin de fonctionnalités spéciales.myarray[x] = 116) or a single string character (e.g.
montableau[x] = "t"). En python 3.x vous sont que autorisé à utiliser les nombres entiers; la tentative de définir une chaîne de valeur de l'index d'un objet bytearray entraînera une erreur TypeError.bytearray[n]
exige des éléments de type int. Vous pouvez toujours manipuler bytearrays en termes de "chaînes" à l'aide de découpage, bien quefoo[3] = 'x'
ne fonctionne pas,foo[3:4] = b'x'
fonctionne très bien. Vous devez spécifier le début et la fin de positions pour le remplacement de travailler, et vous devez utiliser unbytes
valeur, un python3str
n'est pas autorisé.Cette réponse a été sans vergogne arraché de ici
Exemple 1: Assemblage d'un message à partir de fragments
Supposons que vous êtes l'écriture de code de réseau qui reçoit un message de grande taille sur une connexion de socket. Si vous savez au sujet de douilles, vous savez que le
recv()
opération n'attendez pas que toutes les données arrivent. Au lieu de cela, il se contente de ce qui est actuellement disponible dans les tampons du système. Par conséquent, pour obtenir toutes les données, vous pouvez écrire du code qui ressemble à ceci:Le seul problème avec ce code, c'est que la concaténation (
+=
) a des performances horribles. Par conséquent, une commune de l'optimisation de la performance en Python 2 est de rassembler tous les morceaux dans une liste et effectuer une jointure lorsque vous avez terminé. Comme ceci:Maintenant, voici une troisième solution à l'aide d'un
bytearray
:Remarquez comment le
bytearray
version est vraiment très propre. Vous n'avez pas de collecter des pièces dans une liste et vous n'effectuez pas que cryptic rejoindre à la fin. Nice.Bien sûr, la grande question est de savoir si ou non il effectue. Pour un test, j'ai d'abord fait une liste de petites octet fragments comme ceci:
J'ai ensuite utilisé le module timeit de comparer les deux fragments de code:
Lors de l'essai, la version 1 du code couru dans 99.8 s alors que la version 2 a couru dans 116.6 s (une version à l'aide de
+=
concaténation prend 230.3 s par comparaison). Ainsi, alors que l'exécution d'une opération de jointure est encore plus rapide, il est seulement plus rapide d'environ 16%. Personnellement, je pense que le nettoyeur de la programmation de labytearray
version peut faire pour elle.Exemple 2: Binaire d'enregistrement d'emballage
Cet exemple est une légère torsion sur le dernier exemple. Supposons que vous avez eu un grand Python liste d'entiers (x,y) les coordonnées. Quelque chose comme ceci:
points = [(1,2),(3,4),(9,10),(23,14),(50,90),...]
Maintenant, supposons que vous avez besoin d'écrire des données binaires codées fichier constitué d'un entier de 32 bits longueur suivie par chaque point emballés dans une paire de nombres entiers de 32 bits. Une façon de le faire serait d'utiliser la structure de module comme ceci:
Le seul problème avec ce code, c'est qu'il effectue un grand nombre de petits
write()
opérations. Une approche alternative consiste à emballer le tout dans unbytearray
et uniquement effectuer une opération d'écriture à la fin. Par exemple:Bien sûr, la version qui utilise
bytearray
s'exécute beaucoup plus rapidement. Dans un simple test de chronométrage impliquant une liste de 100000 points, il fonctionne dans environ la moitié du temps que la version qui fait beaucoup de petites écrit.Exemple 3: traitement Mathématique des valeurs d'octets
Le fait que bytearrays se présenter sous la forme de tableaux d'entiers rend plus facile l'exécution de certains types de calculs. Dans un récent des systèmes embarqués de projet, j'ai été à l'aide de Python pour communiquer avec un périphérique sur un port série. Dans le cadre du protocole de communication, tous les messages ont dû être signé avec un contrôle de Redondance Longitudinale (LRC) de l'octet. Un LRC est calculé en prenant un XOR sur toutes les valeurs d'octets.
Bytearrays faire de tels calculs facile. Voici une version:
Voici une version qui augmente votre sécurité d'emploi:
message.append(functools.reduce(lambda x,y:x^y,message))
Et voici le même calcul en Python 2 sans
bytearray
s:Personnellement, j'aime le
bytearray
version. Il n'y a pas besoin d'utiliserord()
et vous pouvez simplement ajouter le résultat à la fin du message au lieu d'utiliser la concaténation.Voici un autre mignon exemple. Supposons que vous vouliez exécuter un
bytearray
par le biais d'un simple XOR-de chiffrement. Voici un one-liner pour le faire:Ici est un lien vers la présentation
b''.join(chunks)
approche (et qui ont été trop paresseux, d'autre part, à faire des benchmarks de moi-même).Si vous regardez la documentation de
bytearray
, il dit:En revanche, la documentation de
octets
dit:Comme vous pouvez le voir, la principale distinction est la mutabilité.
str
des méthodes qui "change", la chaîne fait retour une nouvelle chaîne avec la modification souhaitée. Alors quebytearray
méthodes qui modifient la séquence effectivement changer la séquence de.Vous préférez utiliser
bytearray
, si vous modifiez un objet de grande taille (par exemple, un des pixels de l'image de la mémoire tampon) par le biais de sa représentation binaire et vous souhaitez que les modifications à faire sur place pour plus d'efficacité.bytearray
méthodes, dont beaucoup sont décrits comme "renvoi d'une copie de l'objet/seq." (comme de 3.6). Je ne suis pas certain mais je pense que le principal avantage est la possibilité d'accéder potentiellement tampons de grande taille sans intermédiaire de la copie (dans des objets python, probablement pour la plupart des chaînes?); donc, pour la mutabilité je pense que l'avantage vient de l'indexation/découpage au lieu de méthodes qui en fait muter 'bytearray, etc.Wikipedia fournit un exemple de Chiffrement XOR à l'aide de Python bytearrays (docstrings réduit):
vernam_encrypt = vernam_decrypt = lambda data, key: bytearray(a^b for a, b in zip(*map(bytearray, [data, key])))
print(binascii.hexlify(key).decode())
pour imprimer la clé sous forme de chaîne hexadécimale. Pour la convertir:key = binascii.unhexlify(hex_string)
.