Konvertieren variable-sized-byte-array zu einem integer/long
Wie kann ich umwandeln eine (big-endian) variable-sized-Binär-byte-array in ein (unsigned) integer/long? Als Beispiel '\x11\x34'
stellt 4404
Gerade jetzt, ich bin mit
def bytes_to_int(bytes):
return int(bytes.encode('hex'), 16)
Die ist klein und leicht lesbar, aber wohl nicht sehr effizient. Gibt es eine bessere (offensichtlicher) Weise?
InformationsquelleAutor der Frage goncalopp | 2014-08-12
Du musst angemeldet sein, um einen Kommentar abzugeben.
Python nicht traditionell viel Einsatz für "zahlen im big-endian-C layout" zu groß sind C. (Wenn man sich mit 2-byte, 4-byte oder 8-byte-zahlen, dann
struct.unpack
ist die Antwort.)Aber genug Leute, die krank von es nicht eine offensichtliche Weg, dies zu tun, die Python 3.2 Hinzugefügt eine Methode
int.from_bytes
das genau das tut, was Sie wollen:Leider, wenn Sie eine ältere version von Python, die Sie nicht haben. Also, welche Optionen Sie haben? (Neben den offensichtlichen one: update auf 3.2, oder, besser, 3.4...)
Ersten, da ist dein code. Ich denke
binascii.hexlify
ist eine bessere Art und Weise zu buchstabieren es als.encode('hex')
weil "encode" hat immer schien ein wenig seltsam für ein Verfahren auf byte-Zeichenfolgen (im Gegensatz zu Unicode-strings), und es ist in der Tat verbannt in Python 3. Aber ansonsten scheint es ziemlich gut lesbar und offensichtlich zu mir. Und es sollte Recht schnell gehen—ja, es ist zum erstellen einer temporären string, aber es tut allen einen looping und Arithmetik in C (zumindest CPython), die im Allgemeinen eine um eine Größenordnung oder zwei schneller als in Python. Es sei denn, Ihrbytearray
ist so groß, dass die Zuordnung der Zeichenfolge selbst wird kostspielig werden, ich würde nicht sorgen über die performance hier.Alternativ könnte man es machen, in einer Schleife. Aber das ist Ausführlicher und, zumindest in CPython, viel langsamer.
Könnten Sie versuchen, zu beseitigen, die explizite Schleife für eine implizite, aber die offensichtliche Funktion zu tun, ist
reduce
die als un-Pythonic, die ein Teil der Gemeinschaft—und es ist natürlich zu verlangen, dass Sie eine Funktion aufrufen, die für jedes byte.Könnten Sie entrollen der Schleife oder
reduce
durch das brechen Sie in Stücke von 8 bytes und Schleifen überstruct.unpack_from
oder nur dabei eine großestruct.unpack('Q'*len(b)//8 + 'B' * len(b)%8)
- und looping über, aber das macht es viel weniger lesbar und wahrscheinlich auch nicht viel schneller.Könnten Sie NumPy... aber wenn Sie größer als 64 oder vielleicht 128 bit, es wird am Ende alles konvertieren zu Python-Objekten sowieso.
So, ich denke, deine Antwort ist die beste option.
Hier sind einige timings zu vergleichen das offensichtlichste manuelle Konvertierung:
Zum Vergleich in Python 3.4:
Also, Ihre Methode ist immer noch ziemlich schnell...
InformationsquelleAutor der Antwort abarnert
Funktion struct.entpacken(...) tut, was Sie brauchen.
InformationsquelleAutor der Antwort Curd