Ký tự 'b' làm gì trước một chuỗi ký tự?


831

Rõ ràng, sau đây là cú pháp hợp lệ:

my_string = b'The string'

Tôi muốn biết:

  1. bKý tự này ở phía trước chuỗi có nghĩa là gì?
  2. Tác dụng của việc sử dụng nó là gì?
  3. Các tình huống thích hợp để sử dụng nó là gì?

Tôi đã tìm thấy một câu hỏi liên quan ngay trên SO, nhưng câu hỏi đó là về PHP và nó nói rằng nó bđược sử dụng để chỉ ra chuỗi là nhị phân, trái ngược với Unicode, cần mã để tương thích với phiên bản PHP <6 , khi di chuyển sang PHP 6. Tôi không nghĩ điều này áp dụng cho Python.

Tôi đã tìm thấy tài liệu này trên trang Python về việc sử dụng một uký tự trong cùng một cú pháp để chỉ định một chuỗi là Unicode. Thật không may, nó không đề cập đến ký tự b ở bất cứ đâu trong tài liệu đó.

Ngoài ra, chỉ vì tò mò, có nhiều biểu tượng hơn bulàm những việc khác không?

Câu trả lời:


416

Để trích dẫn tài liệu Python 2.x :

Tiền tố của 'b' hoặc 'B' bị bỏ qua trong Python 2; nó chỉ ra rằng chữ sẽ trở thành một byte bằng chữ trong Python 3 (ví dụ: khi mã được tự động chuyển đổi với 2to3). Tiền tố 'u' hoặc 'b' có thể được theo sau bởi tiền tố 'r'.

Các Python 3 tài liệu trạng thái:

Byte chữ luôn luôn có tiền tố là 'b' hoặc 'B'; chúng tạo ra một thể hiện của kiểu byte thay vì kiểu str. Chúng chỉ có thể chứa các ký tự ASCII; các byte có giá trị số từ 128 trở lên phải được thể hiện bằng các thoát.


4
Vì vậy, có vẻ như Python <v3 sẽ bỏ qua ký tự phụ này. Điều gì sẽ là một trường hợp trong v3 khi bạn sẽ cần sử dụng chuỗi ab thay vì chỉ là một chuỗi thông thường?
Jesse Webb

5
@Gweebz - nếu bạn thực sự gõ một chuỗi trong một mã hóa cụ thể thay vì thoát mã unicode (ví dụ: b '\ xff \ xfe \ xe12' thay vì '\ u32e1').
gièm pha

7
Trên thực tế, nếu bạn đã nhập unicode_literalstừ __future__, điều này sẽ "đảo ngược" hành vi của chuỗi cụ thể này (trong Python 2.x)
Romuald Brunet

34
Một câu chuyện ngôn ngữ đơn giản hơn một chút xung quanh tài liệu được trích dẫn sẽ làm cho câu trả lời này tốt hơn IMHO
Hack-R

2
Mặt khác, là một câu trả lời cho ai đó đã hiểu nó.
Rafael Eyng

680

Python 3.x phân biệt rõ ràng giữa các loại:

  • str = = '...' lít = một chuỗi các ký tự Unicode (UTF-16 hoặc UTF-32, tùy thuộc vào cách Python được biên dịch)
  • bytes= b'...'lít = một chuỗi các octet (số nguyên từ 0 đến 255)

Nếu bạn quen thuộc với Java hoặc C #, hãy nghĩ về stras Stringbytesas byte[]. Nếu bạn quen với SQL, nghĩ strnhư NVARCHARbytesnhư BINARYhay BLOB. Nếu bạn đã quen thuộc với Windows registry, nghĩ đến strnhư REG_SZbytesnhư REG_BINARY. Nếu bạn đã quen thuộc với C (++), thì hãy quên mọi thứ bạn đã học charvà chuỗi, bởi vì MỘT TÍNH NĂNG KHÔNG PHẢI LÀ BYTE . Ý tưởng đó đã lỗi thời.

Bạn sử dụng strkhi bạn muốn đại diện cho văn bản.

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

Bạn sử dụng byteskhi bạn muốn biểu diễn dữ liệu nhị phân cấp thấp như cấu trúc.

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

Bạn có thể mã hóa a strđến một bytesđối tượng.

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

Và bạn có thể giải mã a bytesthành a str.

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

Nhưng bạn không thể tự do trộn lẫn hai loại.

>>> 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

Các b'...'ký hiệu là hơi khó hiểu ở chỗ nó cho phép các byte 0x01-0x7F được xác định với các ký tự ASCII thay vì số hex.

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

Nhưng tôi phải nhấn mạnh, một ký tự không phải là một byte .

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

Trong Python 2.x

Các phiên bản Pre-3.0 của Python thiếu loại phân biệt giữa dữ liệu văn bản và dữ liệu nhị phân. Thay vào đó, đã có:

  • unicode= u'...'chữ = chuỗi ký tự Unicode = 3.xstr
  • str= '...'lít / chuỗi các byte / ký tự bị xáo trộn
    • Thông thường văn bản, được mã hóa trong một số mã hóa không xác định.
    • Nhưng cũng được sử dụng để đại diện cho dữ liệu nhị phân như struct.packđầu ra.

Để giảm bớt quá trình chuyển đổi từ 2.x sang 3.x, b'...'cú pháp bằng chữ đã được nhập vào Python 2.6, để cho phép phân biệt các chuỗi nhị phân (nên bytesở 3.x) với các chuỗi văn bản (nên strở trong 3 .x). Các btiền tố không có gì trong 2.x, nhưng kể2to3 kịch bản không để chuyển đổi nó thành một chuỗi Unicode trong 3.x.

Vì vậy, có, nghĩa b'...'đen trong Python có cùng mục đích mà chúng làm trong PHP.

Ngoài ra, chỉ vì tò mò, có nhiều biểu tượng hơn b và u làm những việc khác không?

Các rtiền tố tạo ra một chuỗi nguyên (ví dụ, r'\t'là một dấu gạch chéo + tthay vì một tab), và dấu ngoặc kép ba '''...'''hoặc """..."""cho phép nhiều dòng chuỗi literals.


2
Cảm ơn! Tôi đã hiểu nó sau khi đọc những câu sau: "Để giảm bớt quá trình chuyển đổi 2.x-sang-3.x, cú pháp chữ b '...' đã được nhập vào Python 2.6, để cho phép phân biệt các chuỗi nhị phân (cần phân biệt là byte trong 3.x) từ các chuỗi văn bản (nên là str trong 3.x). Tiền tố b không làm gì trong 2.x, nhưng nói với kịch bản 2to3 không chuyển đổi nó thành chuỗi Unicode trong 3.x. "
tommy.carstensen

4
Các 'A' == b'A' --> Falsekiểm tra thực sự làm cho nó rõ ràng. Phần còn lại của nó là tuyệt vời, nhưng cho đến thời điểm đó tôi đã không hiểu đúng rằng một chuỗi byte không thực sự là văn bản.
tự đại diện

12
'שלום עולם' == 'hello world'
Eli

12
Điều này rõ ràng hơn nhiều so với câu trả lời được chấp nhận chỉ trích dẫn tài liệu. Các tài liệu đối với tôi không có ý nghĩa vì vậy cung cấp thêm bối cảnh trong tài liệu là tuyệt vời. Cảm ơn!
rayryeng

2
b "một số chuỗi" .decode ('UTF-8'), tôi tin rằng đó là dòng mà nhiều người đang tìm kiếm
Marvin Thobejane

22

B biểu thị một chuỗi byte.

Byte là dữ liệu thực tế. Chuỗi là một trừu tượng.

Nếu bạn có đối tượng chuỗi nhiều ký tự và bạn đã lấy một ký tự, thì đó sẽ là một chuỗi và nó có thể có kích thước hơn 1 byte tùy thuộc vào mã hóa.

Nếu lấy 1 byte bằng chuỗi byte, bạn sẽ nhận được một giá trị 8 bit duy nhất từ ​​0-255 và nó có thể không đại diện cho một ký tự hoàn chỉnh nếu các ký tự do mã hóa là> 1 byte.

TBH Tôi sẽ sử dụng các chuỗi trừ khi tôi có một số lý do cấp thấp cụ thể để sử dụng byte.


16

Từ phía máy chủ, nếu chúng tôi gửi bất kỳ phản hồi nào, nó sẽ được gửi dưới dạng byte, vì vậy nó sẽ xuất hiện trong máy khách dưới dạng b'Response from server'

Để thoát khỏi b'....' chỉ cần sử dụng mã dưới đây:

Tập tin máy chủ:

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

Tệp khách hàng:

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

sau đó nó sẽ in Response from server


1
Nó không giải thích câu hỏi mà Jesse Webb đã hỏi!
Chandra Kanth

Tôi đã nói rằng không sử dụng các phương thức mã hóa và giải mã, đầu ra chuỗi sẽ có tiền tố là b '' vì python lấy nó làm kiểu byte thay vì kiểu chuỗi. Nếu bạn không muốn có đầu ra như b '... 'sử dụng những điều trên đó. Bạn không hiểu gì?
Nani Chintha

Trên thực tế đây chính xác là câu trả lời cho tiêu đề của câu hỏi đã được hỏi: Q: "B'x 'làm gì?" A: "Nó hiện 'x'.encode ()" Đó đúng là những gì nó làm. Phần còn lại của câu hỏi muốn biết nhiều hơn thế, nhưng tiêu đề được trả lời.
Michael Erickson

10

Đây là một ví dụ trong đó sự vắng mặt bsẽ tạo ra một TypeErrorngoại lệ trong 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

Thêm một btiền tố sẽ khắc phục vấn đề.


9

Nó biến nó thành một bytesnghĩa đen (hoặcstr trong 2.x), và có giá trị cho 2.6+.

Các rtiền tố gây backslashes được "uninterpreted" (không bỏ qua, và sự khác biệt không vấn đề).


Điều này nghe có vẻ sai theo tài liệu trích dẫn trong câu trả lời của aix; b sẽ bị bỏ qua trong phiên bản Python ngoài 3.
Jesse Webb

2
Nó sẽ là một strtrong 2.x, vì vậy có thể nói rằng nó bị bỏ qua. Sự khác biệt quan trọng khi bạn nhập unicode_literalstừ __future__mô-đun.
Ignacio Vazquez-Abrams

6

Ngoài những gì người khác đã nói, lưu ý rằng một ký tự đơn trong unicode có thể bao gồm nhiều byte .

Cách unicode hoạt động là nó lấy định dạng ASCII cũ (mã 7 bit trông giống 0xxx xxxx) và thêm các chuỗi nhiều byte trong đó tất cả các byte bắt đầu bằng 1 (1xxx xxxx) để thể hiện các ký tự ngoài ASCII để Unicode sẽ bị ngược - Tương thích với 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

Bạn có thể sử dụng JSON để chuyển đổi nó thành từ điển

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

{"giá trị cốt lõi"}


BÌNH GIỮ NHIỆT:

Đây là một ví dụ từ bình. Chạy này trên dòng thiết bị đầu cuối:

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

Trong bình / tuyến.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)

{'giá trị cốt lõi'}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.