Wydaje się, że istnieją dwa różne sposoby konwersji ciągu na bajty, jak widać w odpowiedziach na TypeError: „str” nie obsługuje interfejsu bufora
Która z tych metod byłaby lepsza, czy bardziej Pythonic? Czy to tylko kwestia osobistych preferencji?
b = bytes(mystring, 'utf-8')
b = mystring.encode('utf-8')
python
string
character-encoding
python-3.x
Mark Ransom
źródło
źródło
bytes(item, "utf8")
, ponieważ jawne jest lepsze niż niejawne, więc ...str.encode( )
domyślnie cicho na bajty, co czyni cię bardziej Unicode-zen, ale mniej wyraźnym-Zen. Również „wspólne” nie jest terminem, który lubię stosować. Ponadto,bytes(item, "utf8")
jest bardziej podobny dostr()
ib"string"
notacji. Przepraszam, jeśli tak bardzo rozumiem twoje powody. Dziękuję Ci.encode()
nie dzwonibytes()
, to na odwrót. Oczywiście nie jest to od razu oczywiste i dlatego zadałem pytanie.Odpowiedzi:
Jeśli spojrzysz na dokumenty
bytes
, wskazuje to nabytearray
:bytes
Może więc zrobić znacznie więcej niż tylko kodowanie łańcucha. Pythonic pozwala na wywołanie konstruktora z dowolnym typem parametru źródłowego, który ma sens.Myślę, że w przypadku kodowania ciągu
some_string.encode(encoding)
jest to bardziej Pythonic niż używanie konstruktora, ponieważ jest to najbardziej samok dokumentujące - „weź ten ciąg i zakoduj go za pomocą tego kodowania” jest wyraźniejsze niżbytes(some_string, encoding)
- nie ma wyraźnego czasownika podczas używania konstruktor.Edycja: sprawdziłem źródło Python. Jeśli przekażesz ciąg Unicode, aby
bytes
użyć CPython, wywołuje PyUnicode_AsEncodedString , który jest implementacjąencode
; więc po prostu omijasz poziom pośredni, jeśli nazywaszencode
siebie.Zobacz także komentarz Serdalisa -
unicode_string.encode(encoding)
jest również bardziej Pythoniczny, ponieważ jego odwrotność jestbyte_string.decode(encoding)
i symetria jest ładna.źródło
unicode_string.encode(encoding)
pasuje również,bytearray.decode(encoding)
gdy chcesz odzyskać swój ciąg.bytearray
jest używany, gdy potrzebujesz mutowalnego obiektu. Nie potrzebujesz go do prostych konwersjistr
↔bytes
.bytearray
wyjątkiem tego, że doktorzy zabytes
nie podają szczegółów, po prostu mówią „to jest niezmienna wersjabytearray
”, więc muszę z tego zacytować.bytes
: Unikaj używania typu bajtów jako funkcji z argumentem liczby całkowitej. W wersji 2 zwraca liczbę całkowitą przekonwertowaną na łańcuch (bajtowy), ponieważ bajty to alias dla str, natomiast w wersji 3 zwraca bajtowanie zawierające podaną liczbę znaków null. Na przykład zamiast bajtów wyrażenia v3 (6) użyj równoważnego b '\ x00' * 6, który płynnie działa w ten sam sposób w każdej wersji.byte_string.decode('latin-1')
ponieważutf-8
nie obejmuje całego zakresu od 0x00 do 0xFF (0-255), sprawdź dokumentację python dla więcej informacji.To łatwiejsze niż się wydaje:
źródło
obj.method()
składni zamiastcls.method(obj)
składni, tj. Użyjbytestring = unicode_text.encode(encoding)
iunicode_text = bytestring.decode(encoding)
.self
jako pierwszy argumentencode
jako metoda powiązana z łańcuchem. Ta odpowiedź sugeruje, że zamiast tego należy wywołać metodę niezwiązaną i przekazać jej ciąg. To jedyna nowa informacja w odpowiedzi i jest zła.Absolutnie najlepszym sposobem jest ani o 2, ale 3rd. Pierwszy parametr ma wartość domyślną od czasu Python 3.0. Zatem najlepszym sposobem jest
encode
'utf-8'
Będzie to również szybsze, ponieważ domyślny argument nie powoduje ciągu
"utf-8"
w kodzie C, aleNULL
, co jest znacznie szybsze do sprawdzenia!Oto kilka terminów:
Mimo ostrzeżenia czasy były bardzo stabilne po wielokrotnych przejazdach - odchylenie wynosiło tylko ~ 2 procent.
Używanie
encode()
bez argumentu nie jest zgodne z Python 2, ponieważ w Python 2 domyślnym kodowaniem znaków jest ASCII .źródło
'\u00012345'*10000
. Oba biorą 28,8 na moim laptopie; dodatkowe 50ns jest prawdopodobnie utracone w wyniku błędu zaokrąglania. Oczywiście jest to dość ekstremalny przykład - ale'abc'
jest równie ekstremalny w przeciwnym kierunku.