Bedste måde at konvertere streng til bytes i Python 3?

Der synes at være to forskellige måder at konvertere en streng til bytes på, som det fremgår af svarene på https://stackoverflow.com/questions/5471158/typeerror-str-does-not-support-the-buffer-interface

Hvilken af disse metoder ville være bedre eller mere pythonisk? Eller er det bare et spørgsmål om personlige præferencer?

b = bytes(mystring, 'utf-8')

b = mystring.encode('utf-8')
Løsning

Hvis du kigger i dokumentationen for bytes, peger den på bytearray:

bytearray([source[, encoding[, errors]]]])

Returnerer et nyt array af bytes. Bytearray-typen er en foranderlig sekvens af hele tal i intervallet 0 <= x < 256. Den har de fleste af de sædvanlige metoder for mutable sekvenser, som er beskrevet i Mutable sekvenstyper, samt de fleste metoder, som bytes-typen har, se Bytes og Byte Array-metoder.

Den valgfrie kildeparameter kan bruges til at initialisere arrayet på et par forskellige måder:

Hvis det er en streng, skal du også angive kodningsparametrene (og eventuelt fejl); bytearray() konverterer derefter strengen til bytes ved hjælp af str.encode().

Hvis det er et heltal, vil arrayet have denne størrelse og vil blive initialiseret med nul bytes.

Hvis det er et objekt, der er i overensstemmelse med buffer-interfacet, vil en skrivebeskyttet buffer af objektet blive brugt til at initialisere bytes-arrayet.

Hvis det er en iterabel, skal det være en iterabel af hele tal i intervallet 0 Og uden et argument oprettes et array af størrelse 0.__

bytes kan gøre meget mere end blot at kode en streng. Det'er Pythonisk, at det ville tillade dig at kalde konstruktøren med enhver type kildeparameter, der giver mening.

Til kodning af en streng synes jeg, at some_string.encode(encoding) er mere Pythonisk end at bruge konstruktøren, fordi det er det mest selvdokumenterende -- "take this string and encode it with this encoding" er klarere end bytes(some_string, encoding) -- der er ikke noget eksplicit verbum, når du bruger konstruktøren.

Rediger: Jeg har tjekket Python-kilden. Hvis du overdrager en unicode-streng til bytes ved hjælp af CPython, kalder den PyUnicode_AsEncodedString, som er implementeringen af encode; så du springer bare et indirekte niveau over, hvis du selv kalder encode.

Se også Serdalis' kommentar -- unicode_string.encode(encoding) er også mere Pythonisk, fordi dens inverse er byte_string.decode(encoding) og symmetri er rart.

Kommentarer (5)

Det er nemmere, end man tror:

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
Kommentarer (10)

Den absolut bedste måde er ingen af de to, men den tredje. Den første parameter til encode er default til* 'utf-8' lige siden Python 3.0. Derfor er den bedste måde at gøre det på

b = mystring.encode()

Dette vil også være hurtigere, fordi standardargumentet ikke resulterer i strengen &"utf-8" i C-koden, men NULL, hvilket er meget hurtigere at kontrollere!

Her er nogle tidsangivelser:

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

På trods af advarslen var tiderne meget stabile efter gentagne kørsler - afvigelsen var kun ~2 procent.


Brug af encode() uden et argument er ikke Python 2-kompatibelt, da standardtegnkodningen i Python 2 er ASCII.

>>> 'äöä'.encode()
Traceback (most recent call last):
  File "", line 1, in 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)
Kommentarer (2)