Ich habe versucht, dieses Byte-Objekt in Python 3 zu erstellen:
b'3\r\n'
Also versuchte ich das Offensichtliche (für mich) und fand ein seltsames Verhalten:
>>> bytes(3) + b'\r\n'
b'\x00\x00\x00\r\n'
Anscheinend:
>>> bytes(10)
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
Ich konnte keine Hinweise darauf sehen, warum die Bytekonvertierung auf diese Weise funktioniert, wenn ich die Dokumentation lese. In dieser Python-Ausgabe wurden jedoch einige Überraschungsmeldungen zum Hinzufügen format
zu Bytes gefunden (siehe auch Formatierung von Python 3-Bytes ):
http://bugs.python.org/issue3982
Dies interagiert noch schlechter mit Kuriositäten wie Bytes (int), die jetzt Nullen zurückgeben
und:
Es wäre für mich viel bequemer, wenn Bytes (int) die ASCIIfication dieses Int zurückgeben würden; Aber ehrlich gesagt wäre sogar ein Fehler besser als dieses Verhalten. (Wenn ich dieses Verhalten wollte - das ich nie habe -, wäre es lieber eine Klassenmethode, die wie "bytes.zeroes (n)" aufgerufen wird.)
Kann mir jemand erklären, woher dieses Verhalten kommt?
quelle
3 .to_bytes
Antworten:
So wurde es entworfen - und es ist sinnvoll, weil Sie normalerweise
bytes
eine iterable anstelle einer einzelnen Ganzzahl aufrufen würden :Die Dokumente geben dies an , ebenso wie die Dokumentzeichenfolge für
bytes
:quelle
bytes
ist nur ein Alias fürstr
, was bedeutet, dassbytes([3])
Sie erhalten'[3]'
.bytes([n])
nur für int n von 0 bis 255 funktioniert. Für alles andere wird es ausgelöstValueError
.bytes([3])
immer noch anders ist als das, was das OP wollte - nämlich der Bytewert, der zum Codieren der Ziffer "3" in ASCII verwendet wird, d. H.bytes([51])
, wasb'3'
nicht istb'\x03'
.bytes(500)
erstellt einen Bytestring mit len == 500. Es wird kein Bytestring erstellt, der die Ganzzahl 500 codiert. Und ich stimme zu, dassbytes([500])
dies nicht funktionieren kann, weshalb dies auch die falsche Antwort ist. Wahrscheinlich ist die richtige Antwortint.to_bytes()
für Versionen> = 3.1.Ab Python 3.2 können Sie tun
https://docs.python.org/3/library/stdtypes.html#int.to_bytes
Dementsprechend
x == int_from_bytes(int_to_bytes(x))
. Beachten Sie, dass diese Codierung nur für vorzeichenlose (nicht negative) Ganzzahlen funktioniert.quelle
b"3"
davon kommt3
, wie die Frage stellt. (Es wird gebenb"\x03"
.)Sie können das Paket der Struktur verwenden :
Das ">" ist die Bytereihenfolge (Big-Endian) und das "I" ist das Formatzeichen . Sie können also genau sein, wenn Sie etwas anderes tun möchten:
Dies funktioniert sowohl für Python 2 als auch für Python 3 gleich .
Hinweis: Die inverse Operation (Bytes bis int) kann mit dem Entpacken durchgeführt werden .
quelle
I
,H
, undB
Arbeit , bis ,2**k - 1
wobei k 32, 16, bzw. 8. Bei größeren Eingängen erhöhen sie sichstruct.error
.b'3\r\n'
, dh eine Byte-Zeichenfolge, die das ASCII-Zeichen "3" enthält, nicht das ASCII-Zeichen "\ x03"\x03
, und die Lösung, wenn Sie nur möchten,b'3'
ist trivial. Der von ABB angeführte Grund ist viel plausibler ... oder zumindest verständlich.bytes([x])
und(x).to_bytes()
in Python 3.5. Das war unerwartet.Python 3.5+ führt die% -Interpolation (
printf
Formatierung im Stil) für Bytes ein :Siehe PEP 0461 - Hinzufügen der% -Formatierung zu Bytes und Bytearray .
In früheren Versionen könnten Sie verwenden
str
und.encode('ascii')
das Ergebnis:Hinweis: Es unterscheidet sich von dem, was
int.to_bytes
produziert :quelle
Die Dokumentation sagt:
Die Sequenz:
Es ist das Zeichen '3' (Dezimalzahl 51), das Zeichen '\ r' (13) und '\ n' (10).
Daher würde der Weg es als solches behandeln, zum Beispiel:
Getestet unter IPython 1.1.0 und Python 3.2.3
quelle
bytes(str(n), 'ascii') + b'\r\n'
oderstr(n).encode('ascii') + b'\r\n'
. Vielen Dank! :)"{}\r\n".format(n).encode()
ich glaube nicht, dass es Schaden gibt, wenn die Standard-utf8-Codierung verwendet wirdDie ASCIIfication von 3 ist
"\x33"
nicht"\x03"
!Dafür tut Python, aber für
str(3)
Bytes wäre es völlig falsch, da sie als Arrays von Binärdaten betrachtet und nicht als Zeichenfolgen missbraucht werden sollten.Der einfachste Weg, um das zu erreichen, was Sie wollen
bytes((3,))
, ist besser, alsbytes([3])
weil das Initialisieren einer Liste viel teurer ist. Verwenden Sie daher niemals Listen, wenn Sie Tupel verwenden können. Sie können größere Ganzzahlen mithilfe von konvertierenint.to_bytes(3, "little")
.Das Initialisieren von Bytes mit einer bestimmten Länge ist sinnvoll und am nützlichsten, da sie häufig zum Erstellen eines Puffertyps verwendet werden, für den Sie Speicher mit einer bestimmten zugewiesenen Größe benötigen. Ich benutze dies oft, wenn ich Arrays initialisiere oder eine Datei durch Schreiben von Nullen erweitere.
quelle
b'3'
istb'\x33'
, nichtb'\x32'
. (b)(3)
ist kein Tupel - Sie müssen ein Komma hinzufügen. (c) Das Szenario der Initialisierung einer Sequenz mit Nullen gilt nicht fürbytes
Objekte, da diese unveränderlich sind (es ist jedoch fürbytearray
s sinnvoll ).bytes
undbytearray
denke ich, dass es hauptsächlich um Konsistenz geht. Es ist aber auch nützlich, wenn Sie einige Nullen in einen Puffer oder eine Datei verschieben möchten. In diesem Fall wird sie nur als Datenquelle verwendet.int
(einschließlich Python2long
) kannbytes
mit der folgenden Funktion konvertiert werden:Die umgekehrte Konvertierung kann von einem anderen durchgeführt werden:
Beide Funktionen funktionieren sowohl auf Python2 als auch auf Python3.
quelle
Ich war neugierig auf die Leistung verschiedener Methoden für einen einzelnen Int im Bereich
[0, 255]
und entschied mich daher, einige Timing-Tests durchzuführen.Basierend auf den folgenden Zeitpunkten und dem allgemeinen Trend, den ich beim Ausprobieren vieler verschiedener Werte und Konfigurationen beobachtet habe,
struct.pack
scheint es am schnellsten zu sein, gefolgt vonint.to_bytes
undbytes
, wobeistr.encode
(nicht überraschend) am langsamsten ist. Beachten Sie, dass die Ergebnisse etwas mehr Variationen zeigen als dargestellt,int.to_bytes
undbytes
manchmal das Geschwindigkeitsranking während des Tests geändert haben, aberstruct.pack
eindeutig die schnellsten sind.Ergebnisse in CPython 3.7 unter Windows:
Testmodul (benannt
int_to_byte.py
):quelle
[0, 255]
. Ich nehme an, mit "falschem Indikator" meinen Sie, dass meine Messungen nicht allgemein genug waren, um in die meisten Situationen zu passen? Oder war meine Messmethode schlecht? In letzterem Fall wäre ich interessiert zu hören, was Sie zu sagen haben, aber in letzterem Fall habe ich nie behauptet, dass meine Messungen für alle Anwendungsfälle generisch sind. Für meine (vielleicht Nischen-) Situation beschäftige ich mich nur mit Ints im Bereich[0, 255]
, und das ist das Publikum, das ich mit dieser Antwort ansprechen wollte. War meine Antwort unklar? Ich kann es aus Gründen der Klarheit bearbeiten ...bytes((i,))
anstelle von verwenden,bytes([i])
da die Liste komplexer ist, mehr Speicher benötigt und die Initialisierung lange dauert. In diesem Fall umsonst.Obwohl die vorherige Antwort von brunsgaard eine effiziente Codierung ist, funktioniert sie nur für vorzeichenlose Ganzzahlen. Dieser baut darauf auf, um sowohl für vorzeichenbehaftete als auch für vorzeichenlose Ganzzahlen zu arbeiten.
Wird für den Encoder
(i + ((i * signed) < 0)).bit_length()
verwendet, anstatt nur,i.bit_length()
weil letzterer zu einer ineffizienten Codierung von -128, -32768 usw. führt.Gutschrift: CervEd für die Behebung einer geringfügigen Ineffizienz.
quelle
int_to_bytes(-128, signed=True) == (-128).to_bytes(1, byteorder="big", signed=True)
istFalse
-128
,-32768
usw.(i+(signed*i<0)).bit_length()
Das Verhalten beruht auf der Tatsache, dass in Python vor Version 3
bytes
nur ein Alias für warstr
. In Python3.xbytes
ist eine unveränderliche Version vonbytearray
- völlig neuer Typ, nicht abwärtskompatibel.quelle
Aus Bytes docs :
Dann aus Bytearray-Dokumenten :
Beachten Sie, dass sich das Verhalten von 2.x (wobei x> = 6) unterscheidet, wobei
bytes
einfachstr
:PEP 3112 :
quelle
Einige Antworten funktionieren nicht mit großen Zahlen.
Konvertieren Sie eine Ganzzahl in die Hex-Darstellung und konvertieren Sie sie dann in Bytes:
Ergebnis:
quelle
int.to_bytes
funktioniert mit jeder ganzen Zahl.Wenn die Frage ist, wie eine Ganzzahl selbst (nicht ihr String-Äquivalent) in Bytes konvertiert werden kann, lautet die robuste Antwort meiner Meinung nach:
Weitere Informationen zu diesen Methoden finden Sie hier:
quelle