Parece haver duas formas diferentes de converter uma corda em bytes, como se vê nas respostas a https://stackoverflow.com/questions/5471158/typeerror-str-does-not-support-the-buffer-interface
Qual destes métodos seria melhor ou mais pítonico? Ou é apenas uma questão de preferência pessoal?
b = bytes(mystring, 'utf-8')
b = mystring.encode('utf-8')
Se você olhar os documentos para "bytes", ele aponta para bytearray
:
bytearray([fonte[, codificação[, erros]]])
Devolva um novo conjunto de bytes. O tipo de bytearray é uma sequência mutável de números inteiros no intervalo 0 <= x < 256. Tem a maioria dos métodos usuais de sequências mutáveis, descritos em Tipos de Sequência Muda, assim como a maioria dos métodos que o tipo de bytes tem, veja Métodos de Bytes e Byte Array.
O parâmetro opcional da fonte pode ser usado para inicializar o array de algumas maneiras diferentes:
Se for uma string, você também deve dar os parâmetros de codificação (e opcionalmente, erros); bytearray() então converte a string em bytes usando str.encode().
Se for um número inteiro, o array terá esse tamanho e será inicializado com bytes nulos.
Se for um objeto em conformidade com a interface buffer, um buffer só de leitura do objeto será usado para inicializar a matriz de bytes.
Se for um iterável, deve ser um iterável de inteiros no intervalo 0 <= x < 256, que são usados como o conteúdo inicial do array.
Sem discussão, é criado um array de tamanho 0.
Então "bytes" pode fazer muito mais do que codificar uma string. It's Pythonic que permite que você chame o construtor com qualquer tipo de parâmetro de fonte que faça sentido.
Para codificar uma string, eu acho que some_string.encode(encoding)
é mais Pythonic do que utilizar o construtor, porque ele é o mais auto documentado -- "pegue esta string e codifique-a com esta codificação" é mais claro que bytes(some_string, encoding)
-- não há verbo explícito quando você utiliza o construtor.
Edit: Eu verifiquei a fonte Python. Se você passar uma string unicode para bytes
utilizando CPython, ela chama PyUnicode_AsEncodedString, que é a implementação do encode
; então você'está apenas pulando um nível de indireção se você mesmo chamar o encode
.
Também, veja Serdalis' comente -- unicode_string.encode(encoding)
também é mais Pythonic porque seu inverso é byte_string.decode(encoding)
e a simetria é agradável.
It's mais fácil do que se pensa:
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
O absolutamente melhor caminho não é nenhum dos dois, mas o terceiro. O primeiro parâmetro para encode
defaults to 'utf-8'
desde Python 3.0. Assim, a melhor maneira é
b = mystring.encode()
Isso também será mais rápido, porque o argumento padrão não resulta na string "utf-8"
no código C, mas NULL
, que é muito mais rápido para verificar!
Aqui estão alguns horários:
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
Apesar do aviso, os tempos foram muito estáveis após repetidas corridas - o desvio foi de apenas ~2 por cento.
Utilizando encode()
sem um argumento não é compatível com Python 2, pois em Python 2 a codificação de caracteres padrão é 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)