Sembra che ci siano due modi diversi per convertire una stringa in byte, come si vede nelle risposte a https://stackoverflow.com/questions/5471158/typeerror-str-does-not-support-the-buffer-interface
Quale di questi metodi sarebbe migliore o più pitonico? O è solo una questione di preferenze personali?
b = bytes(mystring, 'utf-8')
b = mystring.encode('utf-8')
Se guardate la documentazione per bytes
, vi indica bytearray
:
bytearray([source[, encoding[, errors]])
restituisce un nuovo array di byte. Il tipo bytearray è una sequenza mutabile di interi nell'intervallo 0 <= x < 256. Ha la maggior parte dei metodi usuali delle sequenze mutabili, descritti in Tipi di sequenze mutabili, così come la maggior parte dei metodi che ha il tipo bytes, vedi Bytes e metodi per array di byte.
Il parametro sorgente opzionale può essere usato per inizializzare l'array in alcuni modi diversi:
Se è una stringa, dovete dare anche i parametri di codifica (e, opzionalmente, gli errori); bytearray() converte quindi la stringa in byte usando str.encode().
Se è un intero, l'array avrà quella dimensione e sarà inizializzato con byte nulli.__
_gt;Se è un oggetto conforme all'interfaccia buffer, un buffer di sola lettura dell'oggetto sarà usato per inizializzare l'array di bytes.
_gt;Se è un iterabile, deve essere un iterabile di interi nell'intervallo 0 <= x <256, che sono usati come contenuto iniziale dell'array.
Senza un argomento, viene creato un array di dimensione 0.
Quindi bytes
può fare molto di più che codificare una stringa. È pitonico che vi permetta di chiamare il costruttore con qualsiasi tipo di parametro sorgente che abbia senso.
Per codificare una stringa, penso che some_string.encode(encoding)
sia più pitonico che usare il costruttore, perché è il più auto-documentante -- "prendi questa stringa e codificala con questa codifica" è più chiaro di bytes(some_string, encoding)
-- non c'è un verbo esplicito quando usi il costruttore.
Modifica: Ho controllato il sorgente Python. Se passate una stringa unicode a bytes
usando CPython, chiama PyUnicode_AsEncodedString, che è l'implementazione di encode
; quindi state solo saltando un livello di indirezione se chiamate voi stessi encode
.
Inoltre, vedi il commento di Serdalis -- unicode_string.encode(encoding)
è anche più pitonico perché il suo inverso è byte_string.decode(encoding)
e la simmetria è bella.
È più facile di quanto si pensi:
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
Il modo assolutamente migliore non è nessuno dei 2, ma il 3°. Il primo parametro di encode
default to 'utf-8'
fin da Python 3.0. Quindi il modo migliore è
b = mystring.encode()
Questo sarà anche più veloce, perché l'argomento di default non risulta nella stringa "utf-8"
nel codice C, ma NULL
, che è molto più veloce da controllare!
Ecco alcuni tempi:
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
Nonostante l'avvertimento i tempi erano molto stabili dopo ripetute esecuzioni - la deviazione era solo ~2 per cento.
Usare encode()
senza un argomento non è compatibile con Python 2, poiché in Python 2 la codifica dei caratteri di default è 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)