Что делает символ "b" перед строковым литералом?

По-видимому, следующий синтаксис

my_string = b'The string'

Я бы хотел знать:

  1. Что означает этот символ b перед символом?
  2. Каковы последствия его использования?
  3. Каковы подходящие ситуации для его использования?

Я нашел связанный вопрос прямо здесь, на SO, но этот вопрос касается PHP, хотя, и он утверждает, что b используется, чтобы указать, что строка двоичная, в отличие от Unicode, которая необходима для того, чтобы код был совместим с версией PHP < 6, при переходе на PHP 6. Я не думаю, что это относится к Python.

Я нашел эту документацию на сайте Python об использовании символа u в том же синтаксисе, чтобы указать строку как Unicode. К сожалению, он не упоминает символ b нигде в этом документе.

Кроме того, только из любопытства, есть ли больше символов, чем b и u которые делают другие вещи?

Ответы

Ответ 1

Чтобы процитировать документацию по Python 2.x:

Префикс 'b' или 'B' игнорируется в Python 2; это указывает на то, что литерал должен стать байтовым литералом в Python 3 (например, когда код автоматически конвертируется с 2to3). За префиксом "u" или "b" может следовать префикс "r".

Документация Python 3 гласит:

Байтные литералы всегда начинаются с префикса 'b' или 'B'; они создают экземпляр типа байтов вместо типа str. Они могут содержать только символы ASCII; байты с числовым значением 128 или более должны быть выражены с помощью экранирования.

Ответ 2

Python 3.x дает четкое различие между типами:

  • str= '...' litals = последовательность символов Unicode (UTF-16 или UTF-32, в зависимости от того, как был скомпилирован Python)
  • bytes= b'...' литералы = последовательность октетов (целые числа от 0 до 255)

Если вы знакомы с Java или С#, подумайте о str как String и bytes как byte[]. Если вы знакомы с SQL, подумайте о str как NVARCHAR и bytes как BINARY или BLOB. Если вы знакомы с реестром Windows, подумайте о str как REG_SZ и bytes как REG_BINARY. Если вы знакомы с C (++), забудьте все, что вы узнали о char и строках, потому что ХАРАКТЕР НЕ БЫТЬ. Эта идея давно устарела.

Вы используете str, когда хотите представить текст.

print('שלום עולם')

Вы используете bytes, когда хотите представлять низкоуровневые двоичные данные, такие как structs.

NaN = struct.unpack('>d', b'\xff\xf8\x00\x00\x00\x00\x00\x00')[0]

Вы можете закодировать a str объекту bytes.

>>> '\uFEFF'.encode('UTF-8')
b'\xef\xbb\xbf'

И вы можете декодировать bytes в str.

>>> b'\xE2\x82\xAC'.decode('UTF-8')
'€'

Но вы не можете свободно смешивать два типа.

>>> b'\xEF\xBB\xBF' + 'Text with a UTF-8 BOM'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat bytes to str

Обозначение b'...' несколько сбивает с толку, поскольку оно позволяет указывать байты 0x01-0x7F с символами ASCII вместо шестнадцатеричных чисел.

>>> b'A' == b'\x41'
True

Но я должен подчеркнуть, символ не является байтом.

>>> 'A' == b'A'
False

В Python 2.x

В версиях версии Python версии 3.0 не было такого различия между текстовыми и двоичными данными. Вместо этого было:

  • unicode= u'...' литералы = последовательность символов Юникода = 3.x str
  • str= '...' литералы = последовательности смешанных байтов/символов
    • Обычно текст, закодированный в некоторой неопределенной кодировке.
    • Но также используется для представления двоичных данных типа struct.pack.

Чтобы облегчить переход 2.x-to-3.x, синтаксис b'...' literal был отправлен обратно в Python 2.6, чтобы позволить различать двоичные строки (которые должны быть bytes в 3.x) из текстовых строк (что должно быть str в 3.x). Префикс b ничего не делает в 2.x, но сообщает 2to3 script не преобразовывать его в строку Unicode в 3.x.

Итак, да, b'...' литералы в Python имеют ту же цель, что и в PHP.

Кроме того, просто из любопытства, есть больше символов, чем b и u, которые делают другие вещи?

Префикс r создает необработанную строку (например, r'\t' - обратная косая черта + t вместо вкладки), а тройные кавычки '''...''' или """...""" позволяют многострочные строковые литералы.

Ответ 3

b обозначает байтовую строку.

Байт - это фактические данные. Строки - это абстракция.

Если у вас был многосимвольный строковый объект, и вы взяли один символ, это была бы строка, и она могла бы быть размером более 1 байта в зависимости от кодировки.

Если взять 1 байт с байтовой строкой, вы получите одно 8-битное значение от 0-255, и оно может не представлять полный символ, если эти символы из-за кодирования были > 1 байт.

TBH Я бы использовал строки, если у меня не было определенной причины низкого уровня для использования байтов.

Ответ 4

Со стороны сервера, если мы отправим какой-либо ответ, он будет отправлен в виде байтового типа, поэтому он будет отображаться на клиенте как b'Response from server'

Чтобы избавиться от b'....', просто используйте следующий код:

Файл сервера:

stri="Response from server"    
c.send(stri.encode())

Клиентский файл:

print(s.recv(1024).decode())

тогда он напечатает Response from server

Ответ 5

Он превращает его в литерал bytes (или str в 2.x) и действителен для 2.6 +.

Префикс r вызывает обратную косую черту как "неинтерпретированную" (не игнорируется, и разница имеет значение).

Ответ 6

Вот пример, где отсутствие b вызовет исключение TypeError в Python 3.x

>>> f=open("new", "wb")
>>> f.write("Hello Python!")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' does not support the buffer interface

Добавление префикса b решит проблему.

Ответ 7

В дополнение к тому, что говорили другие, обратите внимание, что один символ в юникоде может состоять из нескольких байтов.

Работа юникода заключается в том, что он взял старый формат ASCII (7-битный код, который выглядит как 0xxx xxxx) и добавил многобайтовые последовательности, где все байты начинаются с 1 (1xxx xxxx), чтобы представлять символы за пределами ASCII, чтобы Unicode был назад совместим с ASCII.

>>> len('Öl')  # German word for 'oil' with 2 characters
2
>>> 'Öl'.encode('UTF-8')  # convert str to bytes 
b'\xc3\x96l'
>>> len('Öl'.encode('UTF-8'))  # 3 bytes encode 2 characters !
3

Ответ 8

Вы можете использовать JSON, чтобы преобразовать его в словарь

import json
data = b'{"key":"value"}'
print(json.loads(data))

{ "Ключ": "значение"}


ФЛЯГА:

Это пример из колбы. Запустите это на терминальной линии:

import requests
requests.post(url='http://localhost(example)/',json={'key':'value'})

В фляге /rout.py

@app.route('/', methods=['POST'])
def api_script_add():
    print(request.data) # --> b'{"hi":"Hello"}'
    print(json.loads(request.data))
return json.loads(request.data)

{ 'Ключ': 'значение'}