J'essayais de construire cet objet bytes en Python 3:
b'3\r\n'
alors j'ai essayé l'évidence (pour moi), et j'ai trouvé un comportement bizarre:
>>> bytes(3) + b'\r\n'
b'\x00\x00\x00\r\n'
Apparemment:
>>> bytes(10)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Je n'ai pas pu voir de pointeurs sur la raison pour laquelle la conversion d'octets fonctionne de cette façon en lisant la documentation. Cependant, j'ai trouvé des messages surprises dans ce problème Python concernant l'ajout format
d'octets (voir aussi le formatage Python 3 octets ):
http://bugs.python.org/issue3982
Cela interagit encore plus mal avec des bizarreries comme bytes (int) renvoyant des zéros maintenant
et:
Ce serait beaucoup plus pratique pour moi si bytes (int) renvoyait l'ASCIIfication de cet int; mais honnêtement, même une erreur serait meilleure que ce comportement. (Si je voulais ce comportement - que je n'ai jamais eu - je préférerais que ce soit une méthode de classe, invoquée comme "bytes.zeroes (n)".)
Quelqu'un peut-il m'expliquer d'où vient ce comportement?
la source
3 .to_bytes
Réponses:
C'est ainsi qu'il a été conçu - et cela a du sens car généralement, vous appelez
bytes
un itérable au lieu d'un seul entier:La documentation indique ceci , ainsi que la docstring pour
bytes
:la source
bytes
est juste un alias pourstr
, ce qui signifie quebytes([3])
vous donne'[3]'
.bytes([n])
ne fonctionne que pour int n de 0 à 255. Pour tout ce qu'il déclencheValueError
.bytes([3])
c'est toujours différent de ce que l'OP voulait - à savoir la valeur d'octet utilisée pour coder le chiffre "3" en ASCII, c'est-à-dire.bytes([51])
, ce qui n'estb'3'
pasb'\x03'
.bytes(500)
crée une chaîne d'octets w / len == 500. Elle ne crée pas une chaîne d'octets qui encode l'entier 500. Et je suis d'accord quebytes([500])
cela ne peut pas fonctionner, c'est pourquoi c'est aussi la mauvaise réponse. La bonne réponse est probablementint.to_bytes()
pour les versions> = 3.1.À partir de python 3.2, vous pouvez faire
https://docs.python.org/3/library/stdtypes.html#int.to_bytes
En conséquence
x == int_from_bytes(int_to_bytes(x))
,. Notez que cet encodage ne fonctionne que pour les entiers non signés (non négatifs).la source
b"3"
de3
, comme la question demande. (Ça va donnerb"\x03"
.)Vous pouvez utiliser le pack de la structure :
Le ">" est l' ordre des octets (big-endian) et le "I" est le caractère de format . Vous pouvez donc être précis si vous souhaitez faire autre chose:
Cela fonctionne de la même manière sur python 2 et python 3 .
Remarque: l'opération inverse (octets en int) peut être effectuée avec unpack .
la source
I
,H
et leB
travail jusqu'à ce que2**k - 1
k est de 32, 16 et 8 respectivement. Pour des intrants plus importants, ils augmententstruct.error
.b'3\r\n'
, c'est-à-dire une chaîne d'octets contenant le caractère ASCII "3" et non le caractère ASCII "\ x03"\x03
, et la solution si vous voulez justeb'3'
est triviale. La raison invoquée par ABB est beaucoup plus plausible ... ou du moins compréhensible.bytes([x])
et(x).to_bytes()
de Python 3.5. C'était inattendu.Python 3.5+ introduit% -interpolation (
printf
formatage -style) pour les octets :Voir PEP 0461 - Ajout de% de mise en forme aux octets et aux bytearray .
Sur les versions antérieures, vous pouvez utiliser
str
et.encode('ascii')
le résultat:Remarque: il est différent de ce qui
int.to_bytes
produit :la source
La documentation dit:
La séquence:
C'est le caractère '3' (décimal 51) le caractère '\ r' (13) et '\ n' (10).
Par conséquent, la manière de le traiter comme tel, par exemple:
Testé sur IPython 1.1.0 et Python 3.2.3
la source
bytes(str(n), 'ascii') + b'\r\n'
oustr(n).encode('ascii') + b'\r\n'
. Merci! :)"{}\r\n".format(n).encode()
je ne pense pas non plus qu'il y ait de mal à utiliser le codage utf8 par défautL'ASCIIfication de 3
"\x33"
ne l' est pas"\x03"
!C'est ce que fait python,
str(3)
mais ce serait totalement faux pour les octets, car ils devraient être considérés comme des tableaux de données binaires et ne pas être abusés comme des chaînes.Le moyen le plus simple d'obtenir ce que vous voulez est
bytes((3,))
, ce qui est mieux quebytes([3])
parce que l' initialisation d'une liste est beaucoup plus coûteuse, donc n'utilisez jamais de listes lorsque vous pouvez utiliser des tuples. Vous pouvez convertir des entiers plus grands en utilisantint.to_bytes(3, "little")
.L'initialisation d'octets avec une longueur donnée a du sens et est la plus utile, car ils sont souvent utilisés pour créer un type de tampon pour lequel vous avez besoin d'une mémoire d'une taille donnée allouée. J'utilise souvent ceci lors de l'initialisation des tableaux ou de l'extension d'un fichier en y écrivant des zéros.
la source
b'3'
isb'\x33'
, notb'\x32'
. (b)(3)
n'est pas un tuple - vous devez ajouter une virgule. (c) Le scénario d'initialisation d'une séquence avec des zéros ne s'applique pas auxbytes
objets, car ils sont immuables (cela a du sens pourbytearray
s, cependant).bytes
etbytearray
, je pense que c'est surtout une question de cohérence. Mais c'est également utile si vous souhaitez insérer des zéros dans un tampon ou un fichier, auquel cas il n'est utilisé que comme source de données.int
(y compris Python2long
) peuvent être convertis enbytes
utilisant la fonction suivante:La conversion inverse peut être effectuée par un autre:
Les deux fonctions fonctionnent à la fois sur Python2 et Python3.
la source
J'étais curieux de connaître les performances de diverses méthodes pour un seul int de la gamme
[0, 255]
, alors j'ai décidé de faire des tests de timing.Sur la base des horaires ci - dessous, et de la tendance générale , je remarquai d'essayer de nombreuses valeurs et configurations,
struct.pack
semble être le plus rapide, suiviint.to_bytes
,bytes
et avecstr.encode
(sans surprise) étant le plus lent. Notez que les résultats montrent un peu plus de variation que ce qui est représenté,int.to_bytes
etbytes
parfois changé de classement de vitesse pendant les tests, maisstruct.pack
c'est clairement le plus rapide.Résultats dans CPython 3.7 sous Windows:
Module de test (nommé
int_to_byte.py
):la source
[0, 255]
. Je suppose que par "mauvais indicateur" vous voulez dire que mes mesures n'étaient pas assez générales pour s'adapter à la plupart des situations? Ou ma méthodologie de mesure était-elle médiocre? Si le dernier, je serais intéressé d'entendre ce que vous avez à dire, mais si le premier, je n'ai jamais prétendu que mes mesures étaient génériques pour tous les cas d'utilisation. Pour ma situation (peut-être de niche), je ne traite que des ints de la gamme[0, 255]
, et c'est à ce public que je comptais m'adresser avec cette réponse. Ma réponse n'était-elle pas claire? Je peux le modifier pour plus de clarté ...bytes((i,))
place debytes([i])
parce que les listes sont plus complexes, utilisent plus de mémoire et prennent du temps à s'initialiser. Dans ce cas, pour rien.Bien que la réponse précédente de brunsgaard soit un encodage efficace, elle ne fonctionne que pour les entiers non signés. Celui-ci s'appuie sur lui pour fonctionner à la fois pour les entiers signés et non signés.
Pour le codeur,
(i + ((i * signed) < 0)).bit_length()
est utilisé au lieu de simplementi.bit_length()
parce que ce dernier conduit à un codage inefficace de -128, -32768, etc.Crédit: CervEd pour avoir corrigé une inefficacité mineure.
la source
int_to_bytes(-128, signed=True) == (-128).to_bytes(1, byteorder="big", signed=True)
isFalse
-128
,-32768
etc.(i+(signed*i<0)).bit_length()
Le comportement vient du fait que dans Python avant la version 3
bytes
était juste un alias pourstr
. Dans Python3.xbytes
est une version immuable debytearray
- type complètement nouveau, pas rétrocompatible.la source
À partir de la documentation d'octets :
Ensuite, à partir de la documentation bytearray :
Notez que cela diffère du comportement 2.x (où x> = 6), où
bytes
est simplementstr
:PEP 3112 :
la source
Certaines réponses ne fonctionnent pas avec de grands nombres.
Convertissez un entier en représentation hexadécimale, puis convertissez-le en octets:
Résultat:
la source
int.to_bytes
fonctionne avec n'importe quel entier.Si la question est de savoir comment convertir un entier lui-même (et non son équivalent chaîne) en octets, je pense que la réponse robuste est:
Plus d'informations sur ces méthodes ici:
la source