Что символ '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 что делать другие вещи?

12 ответов

Решение

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

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

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

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

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]

Вы можете кодировать 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 выход.

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

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

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

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

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

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

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

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

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

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

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

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

файл клиента

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

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

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

Ответ на вопрос таков:

data.encode()

и чтобы его расшифровать (удалите b, потому что иногда это не нужно)

использование:

data.decode())

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

Превращает это в bytes буквальный (или str в 2.x), и действительно для 2.6+.

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

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

Юникод работает так, что он взял старый формат ASCII (7-битный код, который выглядит как 0xxx xxxx) и добавил многобайтовые последовательности, где все байты начинаются с 1 (1xxx xxxx), чтобы представить символы за пределами ASCII, чтобы Юникод был обратным -совместимый с 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

b"hello"не строка (хотя и выглядит так), а последовательность байтов. Это последовательность из 5 чисел, которая, если вы сопоставите их с таблицей символов, будет выглядеть так: h e l l o. Однако само значение не является строкой, Python просто имеет удобный синтаксис для определения последовательностей байтов с использованием текстовых символов, а не самих чисел. Это избавляет вас от набора текста, а также часто последовательности байтов должны интерпретироваться как символы. Однако это не всегда так — например, чтение JPG-файла выдаст внутри последовательность бессмысленных букв. b"..."потому что JPG имеют нетекстовую структуру.

.encode()а также .decode()конвертировать между строками и байтами.

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

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

Ответ на вопросы 1 и 2: b означает, что вы хотите изменить/использовать обычный тип String на тип Byte. Например:

      >>> type(b'')
<class 'bytes'>
>>> type('')
<class 'str'> 

Отвечая на вопросы 3: его можно использовать, когда мы хотим проверить байтовый поток (последовательность байтов) из какого-либо файла/объекта. Т.е. мы хотим проверить дайджест сообщения SHA1 некоторого файла:

      import hashlib

def hash_file(filename):
   """"This function returns the SHA-1 hash of the file passed into it"""

   # make a hash object
   h = hashlib.sha1()

   # open file for reading in binary mode
   with open(filename,'rb') as file:

       # loop till the end of the file
       chunk = 0
       while chunk != b'':
           # read only 1024 bytes at a time
           chunk = file.read(1024)
           h.update(chunk)

   # return the hex representation of digest
   return h.hexdigest()

message = hash_file("somefile.pdf")
print(message)

bytes(somestring.encode()) - это решение, которое сработало для меня в python 3.

      def compare_types():
    output = b'sometext'
    print(output)
    print(type(output))


    somestring = 'sometext'
    encoded_string = somestring.encode()
    output = bytes(encoded_string)
    print(output)
    print(type(output))


compare_types()
Другие вопросы по тегам