Что символ 'b' делает перед строковым литералом? - PullRequest
632 голосов
/ 07 июня 2011

Видимо, следующий допустимый синтаксис

my_string = b'The string'

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

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

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

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

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

Ответы [ 8 ]

533 голосов
/ 08 июня 2011

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

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

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

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

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

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

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'...' литералы = последовательность символов Unicode = 3.x str
  • str = '...' литералы = последовательностисмешанных байтов / символов
    • Обычно текст, закодированный в некоторой неопределенной кодировке.
    • Но также используется для представления двоичных данных, таких как struct.pack output.

Для облегчения перехода с 2.x на 3.x буквальный синтаксис b'...' был перенесен в Python 2.6, чтобы можно было различать двоичные строки (которые должны быть bytes в 3.x) из текстовых строк (которые должны быть str в 3.x).Префикс b ничего не делает в 2.x, но говорит скрипту 2to3 не преобразовывать его в строку Unicode в 3.x.

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

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

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

327 голосов
/ 07 июня 2011

Цитируя документацию по Python 2.x :

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

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

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

16 голосов
/ 07 июня 2011

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

Байты являются фактическими данными.Строки являются абстракцией.

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

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

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

8 голосов
/ 17 августа 2018

Со стороны сервера, если мы отправим какой-либо ответ, он будет отправлен в виде байтового типа. Так он будет отображаться в клиенте как Ответ от сервера '

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

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

файл клиента

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

тогда будет напечатано

Ответ от сервера

8 голосов
/ 07 июня 2011

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

Префикс r делает обратные слэши «не интерпретированными» (неигнорируется, и разница имеет значение .

7 голосов
/ 23 июня 2014

Вот пример, где отсутствие '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' решит проблему.

2 голосов
/ 07 марта 2018

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

Способ работы Unicode заключается в том, что он взял старый формат 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
0 голосов
/ 14 мая 2019

Вы можете использовать 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)

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

...