Atrodo, kad yra du skirtingi būdai, kaip konvertuoti eilutę į baitus, kaip matyti iš https://stackoverflow.com/questions/5471158/typeerror-str-does-not-support-the-buffer-interface atsakymų.
Kuris iš šių būdų būtų geresnis ar labiau pitoniškas? O gal tai tik asmeninių pageidavimų reikalas?
b = bytes(mystring, 'utf-8')
b = mystring.encode('utf-8')
Jei pažvelgsite į bytes
dokumentus, juose rasite nuorodą į bytearray
:
bytearray([source[, encoding[, errors]]])
Grąžinkite naują baitų masyvą. Tipas bytearray yra keičiama sveikųjų skaičių seka intervale 0 <= x < 256. Jis turi daugumą įprastinių keičiamų sekų metodų, aprašytų skyriuje Keičiamų sekų tipai, taip pat daugumą metodų, kuriuos turi baitų tipas, žr. skyriuje Baitų ir baitų masyvų metodai.
Neprivalomasis šaltinio parametras gali būti naudojamas inicializuoti masyvą keliais skirtingais būdais:
Jeigu tai yra eilutė, taip pat turite nurodyti kodavimo (ir pasirinktinai klaidų) parametrus; tada funkcija bytearray() konvertuoja eilutę į baitus naudodama str.encode().
Jeigu tai yra sveikasis skaičius, masyvas bus tokio dydžio ir bus inicializuotas nuliniais baitais.
Jeigu tai objektas, atitinkantis buferio sąsają, inicializuojant baitų masyvą bus naudojamas tik skaitymui skirtas objekto buferis.
Jeigu tai yra iteruojamasis objektas, tai turi būti iteruojamasis sveikųjų skaičių intervalas 0 <= x < 256, kurie naudojami kaip pradinis masyvo turinys.
Jeigu nėra argumento, sukuriamas 0 dydžio masyvas.
Taigi, bytes
gali atlikti daug daugiau nei tik užkoduoti eilutę. Pitoniška, kad jis leistų iškviesti konstruktorių su bet kokio tipo šaltinio parametru, kuris yra prasmingas.
Manau, kad eilutės kodavimui bytes(some_string.encode(encoding)
yra labiau pitoniška nei konstruktoriaus naudojimas, nes tai yra labiausiai save dokumentuojantis veiksmažodis -- "imk šią eilutę ir užkoduok ją šiuo kodavimu" yra aiškiau nei bytes(some_string, encoding)
-- naudojant konstruktorių nėra aiškaus veiksmažodžio.
redaguoti: Patikrinau Python šaltinį. Jei perduodate vienakodę eilutę į bytes
naudodami CPython, ji iškviečia PyUnicode_AsEncodedString, kuris yra encode
realizacija; taigi, jei patys iškviečiate encode
, tiesiog praleidžiate vieną iš netiesioginio nukreipimo lygių.
Be to, žr. Serdalis komentarą -- unicode_string.encode(encoding)
taip pat yra labiau pitoniškas, nes jo atvirkštinis variantas yra byte_string.decode(encoding)
, o simetrija yra maloni.
Tai paprasčiau, nei manoma:
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
absoliučiai geriausias būdas nėra nei vienas iš dviejų, o trečiasis. Pirmasis parametras `encode
nuo Python 3.0 yra 'utf-8'
. Taigi geriausias būdas yra
b = mystring.encode()
Taip pat tai bus greičiau, nes pagal numatytuosius parametrus C kode gaunama ne eilutė "utf-8"
, o NULL
, kurią daug greičiau patikrinti!
Štai keletas laikų:
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
Nepaisant įspėjimo, po pakartotinio paleidimo laikai buvo labai stabilūs - nuokrypis siekė tik ~2 proc.
Naudojant encode()
be argumento, tai nesuderinama su Python 2, nes Python 2 numatytoji simbolių koduotė yra 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)