Apa yang dilakukan karakter 'b' di depan string literal?

832

Rupanya, berikut ini adalah sintaks yang valid:

my_string = b'The string'

Saya ingin tahu:

  1. Apa arti bkarakter ini di depan string?
  2. Apa efek dari menggunakannya?
  3. Apa situasi yang tepat untuk menggunakannya?

Saya menemukan pertanyaan terkait di sini pada SO, tetapi pertanyaan itu adalah tentang PHP, dan menyatakan bdigunakan untuk menunjukkan string adalah biner, bukan Unicode, yang diperlukan untuk kode agar kompatibel dari versi PHP <6 , ketika bermigrasi ke PHP 6. Saya tidak berpikir ini berlaku untuk Python.

Saya memang menemukan dokumentasi ini di situs Python tentang menggunakan ukarakter dalam sintaksis yang sama untuk menentukan string sebagai Unicode. Sayangnya, itu tidak menyebutkan karakter b di manapun dalam dokumen itu.

Juga, hanya karena penasaran, apakah ada lebih banyak simbol daripada bdan uyang melakukan hal-hal lain?

Jesse Webb
sumber

Jawaban:

417

Mengutip dokumentasi Python 2.x :

Awalan 'b' atau 'B' diabaikan dalam Python 2; itu menunjukkan bahwa literal harus menjadi byte byte dalam Python 3 (misalnya ketika kode secara otomatis dikonversi dengan 2to3). Awalan 'u' atau 'b' dapat diikuti oleh awalan 'r'.

The Python 3 dokumentasi negara:

Bytes literal selalu diawali dengan 'b' atau 'B'; mereka menghasilkan turunan dari tipe byte dan bukan tipe str. Mereka hanya boleh berisi karakter ASCII; byte dengan nilai numerik 128 atau lebih besar harus diekspresikan dengan lolos.

NPE
sumber
4
Jadi sepertinya Python <v3 hanya akan mengabaikan karakter tambahan ini. Apa yang akan menjadi kasus di v3 di mana Anda akan perlu menggunakan string ab bukan hanya string biasa?
Jesse Webb
5
@ Gweebz - jika Anda benar-benar mengetik string dalam pengkodean tertentu dan bukan dengan unicode escapes (mis. B '\ xff \ xfe \ xe12' bukan '\ u32e1').
detly
7
Sebenarnya, jika Anda mengimpor unicode_literalsdari __future__, ini akan "membalikkan" perilaku untuk string khusus ini (dengan Python 2.x)
Romuald Brunet
34
Sebuah narasi bahasa yang lebih sederhana di sekitar dokumentasi yang dikutip akan menjadikan ini jawaban yang lebih baik IMHO
Hack-R
2
Kalau tidak, adalah jawaban untuk seseorang yang sudah memahaminya.
Rafael Eyng
681

Python 3.x membuat perbedaan yang jelas antara jenis:

  • str= '...'literal = urutan karakter Unicode (UTF-16 atau UTF-32, tergantung pada bagaimana Python dikompilasi)
  • bytes= b'...'literal = urutan oktet (bilangan bulat antara 0 dan 255)

Jika Anda terbiasa dengan Java atau C #, pikirkan strsebagai Stringdan bytessebagai byte[]. Jika Anda terbiasa dengan SQL, pikirkan stras NVARCHARdan bytesas BINARYatau BLOB. Jika Anda terbiasa dengan registri Windows, pikirkan strsebagai REG_SZdan bytessebagai REG_BINARY. Jika Anda terbiasa dengan C (++), lupakan semua yang telah Anda pelajari chardan string, karena KARAKTER BUKAN BYTE . Gagasan itu sudah lama usang.

Anda gunakan strsaat Anda ingin merepresentasikan teks.

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

Anda gunakan bytessaat Anda ingin merepresentasikan data biner tingkat rendah seperti struct.

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

Anda dapat mengkodekan suatu strke bytesobjek.

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

Dan Anda dapat memecahkan kode bytesmenjadi str.

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

Tetapi Anda tidak dapat dengan bebas mencampurkan kedua jenis itu.

>>> 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'...'notasi agak membingungkan dalam yang memungkinkan byte 0x01-0x7F akan ditentukan dengan karakter ASCII bukan nomor hex.

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

Tapi saya harus menekankan, karakter bukan byte .

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

Dalam Python 2.x

Versi Pra-3.0 Python tidak memiliki perbedaan antara teks dan data biner. Sebaliknya, ada:

  • unicode= u'...'literal = urutan karakter Unicode = 3.xstr
  • str= '...'literal = urutan byte / karakter yang dikacaukan
    • Biasanya teks, dikodekan dalam beberapa pengkodean yang tidak ditentukan.
    • Tetapi juga digunakan untuk merepresentasikan data biner seperti struct.packkeluaran.

Untuk memudahkan transisi 2.x ke 3.x, b'...'sintaks literal di-backport ke Python 2.6, untuk memungkinkan pembeda string biner (yang harus bytesdalam 3.x) dari string teks (yang harus strdalam 3 .x). The bprefix tidak apa-apa di 2.x, tapi menceritakan 2to3naskah untuk tidak mengubahnya ke string Unicode di 3.x.

Jadi ya, b'...'literal dalam Python memiliki tujuan yang sama dengan yang mereka lakukan dalam PHP.

Juga, hanya karena penasaran, apakah ada lebih banyak simbol daripada b dan kamu yang melakukan hal lain?

The rprefix menciptakan string mentah (misalnya, r'\t'adalah backslash + tbukan tab), dan kutipan tiga '''...'''atau """..."""memungkinkan multi-line string literal.

dan04
sumber
2
Terima kasih! Saya memahaminya setelah membaca kalimat-kalimat ini: "Untuk memudahkan transisi 2.x ke 3.x, sintaksis b '...' di-backport ke Python 2.6, untuk memungkinkan pembedaan string biner (yang seharusnya menjadi byte dalam 3.x) dari string teks (yang seharusnya str dalam 3.x). Awalan b tidak melakukan apa pun dalam 2.x, tetapi memberitahu skrip 2to3 untuk tidak mengubahnya menjadi string Unicode dalam 3.x. "
tommy.carstensen
4
The 'A' == b'A' --> Falsecek benar-benar membuatnya jelas. Sisanya sangat bagus, tetapi sampai saat itu saya belum benar memahami bahwa byte string sebenarnya bukan teks.
Wildcard
12
'שלום עולם' == 'hello world'
Eli
13
Ini jauh lebih jelas daripada jawaban yang diterima yang hanya mengutip dokumentasi. Dokumentasi bagi saya tidak masuk akal sehingga memberikan konteks lebih lanjut dalam dokumentasi itu luar biasa. Terima kasih!
rayryeng
3
b "some string" .decode ('UTF-8'), saya percaya itulah yang dicari banyak orang
Marvin Thobejane
23

B menunjukkan string byte.

Bytes adalah data aktual. String adalah abstraksi.

Jika Anda memiliki objek string multi-karakter dan Anda mengambil satu karakter, itu akan menjadi string, dan ukurannya mungkin lebih dari 1 byte tergantung pada pengkodean.

Jika mengambil 1 byte dengan string byte, Anda akan mendapatkan nilai 8-bit dari 0-255 dan itu mungkin tidak mewakili karakter lengkap jika karakter yang disebabkan oleh pengkodean itu> 1 byte.

TBH Saya akan menggunakan string kecuali saya punya alasan khusus tingkat rendah untuk menggunakan byte.


sumber
16

Dari sisi server, jika kami mengirim respons, itu akan dikirim dalam bentuk tipe byte, sehingga akan muncul di klien sebagai b'Response from server'

Untuk menghilangkan b'....'cukup gunakan kode di bawah ini:

File server:

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

File klien:

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

maka akan dicetak Response from server

Nani Chintha
sumber
1
Itu tidak menjelaskan pertanyaan yang diajukan Jesse Webb!
Chandra Kanth
Saya mengatakan bahwa tanpa menggunakan metode encode dan decode, output string akan diawali dengan b '' karena python menganggapnya sebagai tipe byte, bukan tipe string. Jika Anda tidak ingin mendapatkan output seperti ... "Gunakan yang di atas itu saja. Apa yang tidak kau mengerti?
Nani Chintha
Sebenarnya ini adalah jawaban tepat untuk judul pertanyaan yang ditanyakan: T: "Apa yang b'x lakukan?" A: "Itu tidak 'x'.encode ()" Itu secara harfiah apa yang dilakukannya. Sisa pertanyaan ingin tahu lebih dari ini, tetapi judulnya dijawab.
Michael Erickson
10

Berikut adalah contoh di mana tidak adanya bakan melempar TypeErrorpengecualian di 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

Menambahkan bawalan akan memperbaiki masalah.

pengguna3053230
sumber
9

Ini mengubahnya menjadi bytesliteral (atau strdalam 2.x), dan valid untuk 2.6+.

The rawalan menyebabkan backslashes untuk "uninterpreted" (tidak diabaikan, dan perbedaan tidak peduli).

Ignacio Vazquez-Abrams
sumber
Ini kedengarannya salah menurut dokumentasi yang dikutip dalam jawaban aix; b akan diabaikan dalam versi Python selain 3.
Jesse Webb
2
Ini akan menjadi strdalam 2.x cara baik, sehingga dapat dikatakan bahwa itu diabaikan. Perbedaannya penting ketika Anda mengimpor unicode_literalsdari __future__modul.
Ignacio Vazquez-Abrams
6

Selain apa yang dikatakan orang lain, perhatikan bahwa satu karakter dalam unicode dapat terdiri dari beberapa byte .

Cara unicode bekerja adalah mengambil format ASCII lama (kode 7-bit yang terlihat seperti 0xxx xxxx) dan menambahkan urutan multi-byte di mana semua byte dimulai dengan 1 (1xxx xxxx) untuk mewakili karakter di luar ASCII sehingga Unicode akan mundur -kompatibel dengan 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
xjcl
sumber
2

Anda dapat menggunakan JSON untuk mengubahnya menjadi kamus

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

{"key": "value"}


LABU:

Ini adalah contoh dari labu. Jalankan ini di jalur terminal:

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

Di labu / routes.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'}

Karam Qusai
sumber