Det verkar finnas två olika sätt att konvertera en sträng till bytes, vilket framgår av svaren på https://stackoverflow.com/questions/5471158/typeerror-str-does-not-support-the-buffer-interface.
Vilken av dessa metoder skulle vara bättre eller mer Pythonisk? Eller är det bara en fråga om personliga preferenser?
b = bytes(mystring, 'utf-8')
b = mystring.encode('utf-8')
Om du tittar på dokumentationen för bytes
hänvisar den dig till [bytearray
] (https://docs.python.org/3/library/functions.html#func-bytearray):
bytearray([source[, encoding[, errors]]])
Returnerar en ny array av bytes. Bytearray-typen är en föränderlig sekvens av heltal i intervallet 0 <= x < 256. Den har de flesta av de vanliga metoderna för föränderliga sekvenser, som beskrivs i Mutabla sekvenstyper, samt de flesta metoder som bytes-typen har, se Metoder för bytes- och byte-arrayer.
Den valfria källparametern kan användas för att initialisera matrisen på några olika sätt:
__Om det är en sträng måste du också ange parametrarna för kodning (och eventuellt fel); bytearray() omvandlar sedan strängen till bytes med hjälp av str.encode().___
Om det är ett heltal kommer arrayen att ha den storleken och initialiseras med noll bytes.
Om det är ett objekt som överensstämmer med buffertgränssnittet kommer en skrivskyddad buffert av objektet att användas för att initialisera bytesarrayn.
Om det är en iterabel måste det vara en iterabel av heltal i intervallet 0 <= x < 256, som används som det initiala innehållet i matrisen.
Och utan argument skapas en array av storlek 0.
Så bytes
kan göra mycket mer än att bara koda en sträng. Det är Pythoniskt att det skulle tillåta dig att anropa konstruktören med vilken typ av källparameter som helst som är meningsfull.
När det gäller kodning av en sträng anser jag att some_string.encode(encoding)
är mer Pythoniskt än att använda konstruktören, eftersom det är det mest självdokumenterande - "ta den här strängen och koda den med den här kodningen" är tydligare än bytes(some_string, encoding)
- det finns inget explicit verb när du använder konstruktören.
Redigering: Jag har kontrollerat Pythons källkod. Om du skickar en unicode-sträng till bytes
med hjälp av CPython, anropar den PyUnicode_AsEncodedString, som är implementeringen av encode
; så du hoppar bara över en indirekt nivå om du anropar encode
själv.
Se även Serdalis' kommentar -- unicode_string.encode(encoding)
är också mer Pythoniskt eftersom dess omvänt är byte_string.decode(encoding)
och symmetri är trevligt.
Det är lättare än 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
Det absolut bästa sättet är inget av de två, utan det tredje. Den första parametern till encode
försvinner till 'utf-8'
ända sedan Python 3.0. Det bästa sättet är alltså
b = mystring.encode()
Detta blir också snabbare, eftersom standardargumentet inte resulterar i strängen &"utf-8"
i C-koden, utan NULL
, vilket är mycket snabbare att kontrollera!
Här är några 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
Trots varningen var tiderna mycket stabila efter upprepade körningar - avvikelsen var bara ~2 procent.
Att använda encode()
utan argument är inte Python 2-kompatibelt, eftersom standardkodsningen i Python 2 är ASCII.
>>> 'äöä'.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)