Es scheint zwei verschiedene Möglichkeiten zu geben, eine Zeichenkette in Bytes umzuwandeln, wie aus den Antworten auf https://stackoverflow.com/questions/5471158/typeerror-str-does-not-support-the-buffer-interface hervorgeht.
Welche dieser Methoden ist besser bzw. pythonischer? Oder ist das nur eine Frage der persönlichen Vorliebe?
b = bytes(mystring, 'utf-8')
b = mystring.encode('utf-8')
Wenn Sie sich die Dokumentation für "Bytes" ansehen, verweist sie auf [Bytearray] (https://docs.python.org/3/library/functions.html#func-bytearray):
bytearray([source[, encoding[, errors]]])
Gibt ein neues Array von Bytes zurück. Der Typ bytearray ist eine veränderbare Folge von Ganzzahlen im Bereich 0 <= x < 256. Er verfügt über die meisten der üblichen Methoden für veränderliche Sequenzen, die in Veränderliche Sequenztypen beschrieben sind, sowie über die meisten Methoden des Typs Bytes, siehe Methoden für Bytes und Bytearrays.
Der optionale Quellparameter kann verwendet werden, um das Array auf verschiedene Weise zu initialisieren:
Wenn es sich um eine Zeichenkette handelt, müssen Sie auch die Parameter für die Kodierung (und optional für Fehler) angeben; bytearray() wandelt die Zeichenkette dann mit str.encode() in Bytes um.
Wenn es sich um eine ganze Zahl handelt, hat das Array diese Größe und wird mit Null-Bytes initialisiert.__
Wenn es sich um ein Objekt handelt, das der Pufferschnittstelle entspricht, wird ein schreibgeschützter Puffer des Objekts verwendet, um das Byte-Array zu initialisieren.__
Wenn es sich um eine Iterable handelt, muss es eine Iterable von Ganzzahlen im Bereich 0 <= x < 256 sein, die als Anfangsinhalt des Arrays verwendet werden.__
Ohne Argument wird ein Array der Größe 0 erzeugt.
Bytes" kann also viel mehr als nur eine Zeichenkette kodieren. Es ist pythonisch, dass es Ihnen erlaubt, den Konstruktor mit jeder Art von Quellparameter aufzurufen, die Sinn macht.
Um eine Zeichenkette zu kodieren, denke ich, dass irgendeine_Zeichenkette.kodieren(kodieren)
pythonischer ist als die Verwendung des Konstruktors, weil es am meisten selbstdokumentierend ist -- "nimm diese Zeichenkette und kodiere sie mit dieser Kodierung" ist klarer als bytes(irgendeine_Zeichenkette, kodieren)
-- es gibt kein explizites Verb, wenn man den Konstruktor verwendet.
Edit: Ich habe den Python-Quelltext überprüft. Wenn man einen Unicode-String an bytes
mit CPython übergibt, ruft es PyUnicode_AsEncodedString auf, was die Implementierung von encode
ist; man überspringt also nur eine Ebene der Indirektion, wenn man encode
selbst aufruft.
Siehe auch Serdalis' Kommentar -- unicode_string.encode(encoding)
ist auch pythonischer, weil seine Umkehrung byte_string.decode(encoding)
ist und Symmetrie schön ist.
Es ist einfacher als man denkt:
my_str = "hello world"
my_str_as_bytes = str.encode(my_str)
type(my_str_as_bytes) # ensure it is byte representation
my_decoded_str = my_str_as_bytes.decode()
type(my_decoded_str) # ensure it is string representation
Der absolut beste Weg ist keiner der beiden, sondern der dritte. Der erste Parameter von encode
ist seit Python 3.0 standardmäßig 'utf-8'
. Der beste Weg ist also
b = mystring.encode()
Dies ist auch schneller, da das Standardargument im C-Code nicht die Zeichenkette "utf-8"
ergibt, sondern NULL
, was viel schneller zu prüfen ist!
Hier sind einige Zeitangaben:
In [1]: %timeit -r 10 'abc'.encode('utf-8')
The slowest run took 38.07 times longer than the fastest.
This could mean that an intermediate result is being cached.
10000000 loops, best of 10: 183 ns per loop
In [2]: %timeit -r 10 'abc'.encode()
The slowest run took 27.34 times longer than the fastest.
This could mean that an intermediate result is being cached.
10000000 loops, best of 10: 137 ns per loop
Trotz der Warnung waren die Zeiten nach wiederholten Durchläufen sehr stabil - die Abweichung betrug nur ~2 Prozent.
Die Verwendung von encode()
ohne ein Argument ist nicht mit Python 2 kompatibel, da in Python 2 die Standard-Zeichenkodierung ASCII ist.
>>> 'äöä'.encode()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)