Що робить символ 'b' перед буквальним рядком?


831

Мабуть, наступним є синтаксис:

my_string = b'The string'

Я хотів би знати:

  1. Що означає цей bперсонаж перед струною?
  2. Які ефекти від його використання?
  3. Які підходящі ситуації для його використання?

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

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

Крім того , просто з цікавості, є більше символів , ніж bта uщо робити інші речі?

Відповіді:


416

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

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

У документації Python 3 зазначено:

Літерали байтів завжди мають префікс "b" або "B"; вони створюють екземпляр типу байтів замість типу str. Вони можуть містити лише символи ASCII; байти з числовим значенням 128 або більше повинні бути виражені пропусками.


4
Отже, звучить, що Python <v3 просто ігнорує цей додатковий символ. Яким буде випадок v3, коли вам потрібно буде використовувати рядок ab, а не звичайну?
Джессі Вебб

5
@Gweebz - якщо ви насправді набираєте рядок у певному кодуванні замість унікод-кодів (наприклад, b '\ xff \ xfe \ xe12' замість '\ u32e1').
detly

7
Насправді, якщо ви імпортуєте unicode_literalsз __future__, це призведе до "зворотного" поводження для цього конкретного рядка (в Python 2.x)
Romuald Brunet

34
Трохи простіший мовний розповідь навколо цитованої документації зробить це кращою відповіддю ІМХО
Hack-R

2
Інакше - це відповідь для того, хто це вже розуміє.
Рафаель Ейн

678

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

The b'...'Нотація кілька заплутаним в тому , що вона дозволяє байти 0x01-0x7F повинні бути вказані з ASCII - символів замість шістнадцяткових цифр.

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

Але я мушу наголосити, персонаж - це не байт .

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

У Python 2.x

У попередніх версіях Python версії 3.0 не мали такого розрізнення між текстовими та бінарними даними. Натомість було:

  • unicode = u'...' літерали = послідовність символів Unicode = 3.xstr
  • str = '...' літерали = послідовності змішаних байтів / символів
    • Зазвичай текст, закодований у деякому не визначеному кодуванні.
    • Але також використовується для представлення двійкових даних, таких як struct.packвихід.

Щоб полегшити перехід від 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замість вкладки), а також потрійні лапки '''...'''або """..."""дозволяють багаторядковим рядкові літерали.


2
Дякую! Я зрозумів це, прочитавши ці речення: "Щоб полегшити перехід 2.x-3.x, буквальний синтаксис b '...' був підтриманий на Python 2.6, щоб дозволити розрізняти бінарні рядки (які повинні бути байтами в 3.x) з текстових рядків (що має бути str у 3.x). Префікс b нічого не робить у 2.x, але каже сценарію 2to3 не перетворювати його у рядок Unicode в 3.x. "
tommy.carstensen

4
'A' == b'A' --> FalseПеревірка дійсно робить це ясно. Решта - чудова, але до цього моменту я не правильно зрозумів, що рядок байтів насправді не є текстом.
Wildcard

12
'שלום עולם' == 'hello world'
Елі

12
Це набагато зрозуміліше, ніж прийнята відповідь, яка лише цитує документацію. Для мене документація не мала сенсу, тому надання подальшого контексту в документації є приголомшливим. Дякую!
rayryeng

2
b "деякий рядок" .decode ("UTF-8"), я вважаю, що саме ця
частина

22

B позначає рядок байтів.

Байти - це фактичні дані. Струни - це абстракція.

Якщо у вас був багатосимвольний рядковий об'єкт і ви взяли один символ, це буде рядок, і він може бути розміром більше 1 байта залежно від кодування.

Якщо ви взяли 1 байт з рядком байтів, ви отримаєте одне 8-бітове значення від 0-255, і воно не може представляти повний символ, якщо ці символи внаслідок кодування> 1 байт.

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


16

З боку сервера, якщо ми надішлемо будь-яку відповідь, він буде надісланий у вигляді байтового типу, тому він з’явиться в клієнті як b'Response from server'

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

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

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

Файл клієнта:

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

тоді він буде надрукований Response from server


1
Це не пояснює питання, яке задав Джессі Вебб!
Чандра Кант

Я говорив, що без використання методів кодування та декодування, вихідний рядок буде префіксом b '', оскільки python прийме його як тип байту, а не тип рядка. Якщо ви не хочете отримати результат, як b '... 'використовуйте вище, це все. Що ви не зрозуміли?
Nani Chintha

Насправді це саме відповідь на назву питання, яке було задано: Питання: "Що робить b'x '?" A: "Це робить 'x'.encode ()" Це буквально те, що він робить. Решта запитань хотіла знати набагато більше, ніж це, але назва відповіді.
Майкл Еріксон

10

Ось приклад, коли відсутність 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префікса виправить проблему.


9

Це перетворює його в bytesбуквальне (або strв 2.x) і дійсне для 2.6+.

rПрефікс викликає зворотні косі бути «необробленому" (не ігнорується, а різниця робить справу).


Це звучить неправильно відповідно до документації, цитованої у відповіді Екса; b буде проігноровано у версії Python, окрім 3.
Jesse Webb

2
Це буде a str в 2.x в будь-якому випадку, тому можна сказати, що це ігнорується. Відмінність має значення при імпорті unicode_literalsз __future__модуля.
Ігнасіо Васкес-Абрамс

6

На додаток до сказаного іншими, зверніть увагу, що один символ у Unicode може складатися з декількох байтів .

Спосіб 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

2

Ви можете використовувати JSON для перетворення його в словник

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

{"key": "value"}


ФЛАСКА:

Це приклад з колби. Запустити це на термінальній лінії:

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

У колбі / route.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)

{'key': 'value'}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.