Что делает символ "b" перед строковым литералом?
По-видимому, следующий синтаксис
my_string = b'The string'
Я бы хотел знать:
- Что означает этот символ
b
перед символом? - Каковы последствия его использования?
- Каковы подходящие ситуации для его использования?
Я нашел связанный вопрос прямо здесь, на 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)
{ 'Ключ': 'значение'}