Лучший способ преобразовать строку в байты в Python 3?

Кажется, существует два разных способа преобразования строки в байты, как видно из ответов TypeError: 'str' не поддерживает буферный интерфейс

Какой из этих методов был бы лучше или более Pythonic? Или это только вопрос личных предпочтений?

b = bytes(mystring, 'utf-8')

b = mystring.encode('utf-8')

Ответ 1

Если вы посмотрите на документы для bytes, он указывает на bytearray:

bytearray ([source [, encoding [, errors]]])

Возвращает новый массив байтов. Тип bytearray является изменяемой последовательностью целых чисел в диапазоне 0 <= x < 256. Он имеет большинство обычных методов изменчивых последовательностей, описанных в Mutable Sequence Types, а также большинство методов, которые имеют тип байтов, см. "Методы байтов и байтов".

Необязательный параметр источника может использоваться для инициализации массива несколькими способами:

Если это строка, вы также должны указать параметры кодирования (и, необязательно, ошибки); bytearray() затем преобразует строку в байты с помощью str.encode().

Если это целое число, массив будет иметь этот размер и будет инициализирован нулевыми байтами.

Если это объект, соответствующий интерфейсу буфера, для инициализации массива байтов будет использоваться буфер только для чтения.

Если он является итерируемым, он должен быть итерабельным из целых чисел в диапазоне 0 <= x < 256, которые используются в качестве исходного содержимого массива.

Без аргумента создается массив размером 0.

Итак, bytes может делать гораздо больше, чем просто кодировать строку. Это Pythonic, что позволит вам вызвать конструктор с любым типом параметра источника, который имеет смысл.

Для кодирования строки я думаю, что some_string.encode(encoding) более Pythonic, чем использование конструктора, потому что он является самым самостоятельным документированием - "взять эту строку и закодировать ее с помощью этой кодировки" более ясно, чем bytes(some_string, encoding) - при использовании конструктора нет явного глагола.

Изменить: Я проверил источник Python. Если вы передаете строку unicode в bytes с помощью CPython, она вызывает PyUnicode_AsEncodedString, которая является реализацией encode; так что вы просто пропускаете уровень косвенности, если вы вызываете encode самостоятельно.

Кроме того, см. комментарий Сердалиса - unicode_string.encode(encoding) также больше Pythonic, потому что его обратный byte_string.decode(encoding) и симметрия хороша.

Ответ 2

Это проще, чем кажется

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

Ответ 3

Абсолютно лучшим способом является не 2, а 3-й. Первый параметр для encode умолчанию 'utf-8' со времен Python 3.0. Таким образом, лучший способ

b = mystring.encode()

Это также будет быстрее, потому что аргумент по умолчанию приводит не к строке "utf-8" в коде C, а к NULL, что намного быстрее проверять!

Вот некоторые моменты:

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

Несмотря на предупреждение, времена были очень стабильными после повторных прогонов - отклонение составляло всего ~ 2%.


Использование encode() без аргумента несовместимо с Python 2, так как в Python 2 кодировка символов по умолчанию - 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)

Ответ 4

Вы можете просто преобразовать строку в байты, используя:

a_string.encode()

и вы можете просто конвертировать байты в строку, используя:

some_bytes.decode()

bytes.decode и str.encode имеют encoding='utf-8' качестве значения по умолчанию.

Следующие функции (взятые из Effective Python) могут быть полезны для преобразования str в bytes и bytes в str:

def to_bytes(bytes_or_str):
    if isinstance(bytes_or_str, str):
        value = bytes_or_str.encode() # uses 'utf-8' for encoding
    else:
        value = bytes_or_str
    return value # Instance of bytes


def to_str(bytes_or_str):
    if isinstance(bytes_or_str, bytes):
        value = bytes_or_str.decode() # uses 'utf-8' for encoding
    else:
        value = bytes_or_str
    return value # Instance of str

Ответ 5

so_string = 'stackoverflow'
so_bytes = so_string.encode( )