Apa perbedaan antara string dan string byte?

209

Saya bekerja dengan perpustakaan yang mengembalikan string byte dan saya perlu mengubahnya menjadi string.

Meskipun saya tidak yakin apa bedanya - jika ada.

Sheldon
sumber

Jawaban:

260

Dengan asumsi Python 3 (dalam Python 2, perbedaan ini sedikit kurang jelas) - string adalah urutan karakter, yaitu unicode codepoints ; ini adalah konsep abstrak, dan tidak dapat langsung disimpan di disk. String byte adalah urutan, tidak mengherankan, byte - hal-hal yang dapat disimpan pada disk. Pemetaan di antara mereka adalah pengkodean - ada cukup banyak (dan sangat banyak kemungkinan) - dan Anda perlu tahu mana yang berlaku dalam kasus tertentu untuk melakukan konversi, karena pengkodean yang berbeda dapat memetakan byte yang sama ke string yang berbeda:

>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-16')
'蓏콯캁澽苏'
>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-8')
'τoρνoς'

Setelah Anda tahu mana yang harus digunakan, Anda dapat menggunakan .decode()metode byte string untuk mendapatkan string karakter yang tepat seperti di atas. Untuk kelengkapan, .encode()metode string karakter sebaliknya:

>>> 'τoρνoς'.encode('utf-8')
b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'
lvc
sumber
7
Untuk memperjelas bagi pengguna Python 2: strtipenya sama dengan bytestipenya; jawaban ini secara setara membandingkan unicodetipe (tidak ada dalam Python 3) dengan strtipe.
craymichael
3
@KshitijSaraogi juga tidak sepenuhnya benar; seluruh kalimat itu diedit dan sedikit disayangkan. Representasi in-memory dari objek Python 3 strtidak dapat diakses atau relevan dari sisi Python; struktur data hanyalah urutan codepoint. Di bawah PEP 393 , pengkodean internal yang tepat adalah salah satu dari Latin-1, UCS2 atau UCS4, dan representasi utf-8 dapat di-cache setelah diminta pertama kali, tetapi bahkan kode C tidak disarankan untuk mengandalkan detail internal ini.
Lvc
1
Jika mereka tidak dapat langsung disimpan di disk, jadi bagaimana mereka disimpan dalam memori?
z33k
2
@ Atau mereka harus dikodekan entah bagaimana secara internal untuk alasan itu, tapi ini bukan paparan dari kode Python seperti Anda tidak perlu peduli tentang bagaimana angka floating point disimpan.
lvc
1
@ChrisStryczynski melihat komentar di atas - tentu saja mereka tersimpan di memori entah bagaimana , tetapi formulir itu secara eksplisit disarikan. Memang, hari-hari ini, ia dapat berubah selama masa program dan berbeda antara string yang berbeda atau bahkan mungkin lebih dari satu (beberapa penyandian di-cache), tergantung pada karakter di dalamnya - tetapi satu-satunya waktu Anda perlu khawatir tentang itu adalah jika Anda meretas implementasi dari tipe string itu sendiri.
Lvc
390

Satu-satunya hal yang dapat disimpan oleh komputer adalah byte.

Untuk menyimpan sesuatu di komputer, Anda harus terlebih dahulu menyandikannya , yaitu mengonversinya menjadi byte. Sebagai contoh:

  • Jika Anda ingin menyimpan musik, Anda harus terlebih dahulu menyandikannya menggunakan MP3,WAV , dll
  • Jika Anda ingin menyimpan gambar, Anda harus terlebih dahulu menyandikannya menggunakan PNG,JPEG , dll
  • Jika Anda ingin menyimpan teks, Anda harus terlebih dahulu menyandikan menggunakan ASCII, UTF-8, dll

MP3, WAV, PNG, JPEG, ASCIIDan UTF-8adalah contoh pengkodean . Pengkodean adalah format untuk mewakili audio, gambar, teks, dll dalam byte.

Dalam Python, string byte hanya itu: urutan byte. Itu tidak bisa dibaca manusia. Di bawah tenda, semuanya harus dikonversi ke string byte sebelum dapat disimpan di komputer.

Di sisi lain, string karakter, sering hanya disebut "string", adalah urutan karakter. Itu bisa dibaca manusia. Sebuah string karakter tidak dapat langsung disimpan di komputer, itu harus dikodekan terlebih dahulu (diubah menjadi string byte) Ada beberapa pengkodean di mana string karakter dapat dikonversi menjadi string byte, seperti ASCIIdan UTF-8.

'I am a string'.encode('ASCII')

Kode Python di atas akan mengkodekan string 'I am a string'menggunakan pengkodean ASCII. Hasil dari kode di atas akan berupa string byte. Jika Anda mencetaknya, Python akan menyatakannya sebagai b'I am a string'. Ingat, bagaimanapun, string byte itu tidak dapat dibaca oleh manusia , hanya saja Python menerjemahkannya dari ASCIIsaat Anda mencetaknya. Dalam Python, string byte diwakili oleh b, diikuti oleh string byteASCII representasi .

String byte dapat didekodekan kembali menjadi string karakter, jika Anda tahu pengkodean yang digunakan untuk menyandikannya.

b'I am a string'.decode('ASCII')

Kode di atas akan mengembalikan string asli 'I am a string' .

Pengkodean dan dekode adalah operasi terbalik. Semuanya harus dikodekan sebelum dapat ditulis ke disk, dan itu harus di-decode sebelum dapat dibaca oleh manusia.

Zenadix
sumber
59
Zenadix pantas mendapatkan pujian di sini. Setelah beberapa tahun berfungsi di lingkungan ini, itu adalah penjelasan pertama yang diklik bersama saya. Saya mungkin menato di lengan saya yang lain (satu lengan sudah memiliki "Minimum Mutlak Setiap Pengembang Perangkat Lunak Sepenuhnya, Pasti Harus Tahu Tentang Unicode dan Set Karakter (Tanpa Alasan!) Oleh Joel Spolsky"
neil.millikin
4
Sangat brilian. Lucid dan mudah dimengerti. Namun, saya ingin menyebutkan bahwa baris ini - "Jika Anda mencetaknya, Python akan menyatakannya sebagai b'I am a string '" berlaku untuk Python3 seperti untuk Python2 byte dan str adalah hal yang sama.
SRC
5
Saya menghadiahkan kepada Anda karunia ini karena menawarkan penjelasan yang sangat bisa dibaca manusia untuk memberikan kejelasan dalam hal ini!
fedorqui 'SO berhenti merugikan'
3
Jawaban yang bagus Satu-satunya hal yang mungkin bisa ditambahkan adalah menunjukkan lebih jelas bahwa secara historis, programmer dan bahasa pemrograman cenderung secara eksplisit atau implisit mengasumsikan bahwa urutan byte dan string ASCII adalah hal yang sama . Python 3 memutuskan untuk secara eksplisit mematahkan asumsi ini, dengan benar IMHO.
nekomatis
4
Tautan ke pos Joel yang disebutkan oleh @ neil.millikin di atas: joelonsoftware.com/2003/10/08/…
Kshitij Saraogi
14

Catatan: Saya akan menguraikan lebih banyak jawaban saya untuk Python 3 karena akhir kehidupan Python 2 sangat dekat.

Dalam Python 3

bytesterdiri dari urutan nilai 8-bit yang tidak ditandatangani, sementara strterdiri dari urutan titik kode Unicode yang mewakili karakter tekstual dari bahasa manusia.

>>> # bytes
>>> b = b'h\x65llo'
>>> type(b)
<class 'bytes'>
>>> list(b)
[104, 101, 108, 108, 111]
>>> print(b)
b'hello'
>>>
>>> # str
>>> s = 'nai\u0308ve'
>>> type(s)
<class 'str'>
>>> list(s)
['n', 'a', 'i', '̈', 'v', 'e']
>>> print(s)
naïve

Meskipun bytesdan strtampaknya bekerja dengan cara yang sama, instance mereka tidak kompatibel satu sama lain, yaitu, bytesdan strinstance tidak dapat digunakan bersama dengan operator seperti >dan +. Selain itu, perlu diingat bahwa perbandingan bytesdan strcontoh untuk kesetaraan, yaitu menggunakan ==, akan selalu dievaluasi Falsebahkan ketika mereka mengandung karakter yang persis sama.

>>> # concatenation
>>> b'hi' + b'bye' # this is possible
b'hibye'
>>> 'hi' + 'bye' # this is also possible
'hibye'
>>> b'hi' + 'bye' # this will fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat str to bytes
>>> 'hi' + b'bye' # this will also fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "bytes") to str
>>>
>>> # comparison
>>> b'red' > b'blue' # this is possible
True
>>> 'red'> 'blue' # this is also possible
True
>>> b'red' > 'blue' # you can't compare bytes with str
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'bytes' and 'str'
>>> 'red' > b'blue' # you can't compare str with bytes
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'str' and 'bytes'
>>> b'blue' == 'red' # equality between str and bytes always evaluates to False
False
>>> b'blue' == 'blue' # equality between str and bytes always evaluates to False
False

Masalah lain ketika berhadapan dengan bytesdan strhadir saat bekerja dengan file yang dikembalikan menggunakan openfungsi bawaan. Di satu sisi, jika Anda ingin membaca atau menulis data biner ke / dari file, selalu buka file menggunakan mode biner seperti 'rb' atau 'wb'. Di sisi lain, jika Anda ingin membaca atau menulis data Unicode ke / dari file, waspadai penyandian default komputer Anda, jadi jika perlu berikan encodingparameter untuk menghindari kejutan.

Dalam Python 2

strterdiri dari urutan nilai 8-bit, sedangkan unicodeterdiri dari urutan karakter Unicode. Satu hal yang perlu diingat adalah bahwa strdan unicodedapat digunakan bersama dengan operator jikastr hanya terdiri dari karakter ASCI 7-bit.

Mungkin bermanfaat untuk menggunakan fungsi pembantu untuk mengkonversi antara strdan unicodedalam Python 2, dan antara bytesdan strdalam Python 3.

lmiguelvargasf
sumber
4

Dari What is Unicode :

Pada dasarnya, komputer hanya berurusan dengan angka. Mereka menyimpan huruf dan karakter lain dengan menetapkan nomor untuk masing-masing karakter.

......

Unicode memberikan angka unik untuk setiap karakter, apa pun platformnya, apa pun programnya, apa pun bahasanya.

Jadi ketika komputer mewakili string, ia menemukan karakter yang tersimpan di komputer string melalui nomor Unicode mereka yang unik dan angka-angka ini disimpan dalam memori. Tetapi Anda tidak dapat secara langsung menulis string ke disk atau mengirimkan string pada jaringan melalui nomor Unicode unik karena angka-angka ini hanyalah angka desimal sederhana. Anda harus menyandikan string ke byte string, seperti UTF-8. UTF-8adalah pengkodean karakter yang mampu mengkodekan semua karakter yang mungkin dan menyimpan karakter sebagai byte (seperti ini ). Jadi string yang disandikan dapat digunakan di mana-mana karena UTF-8hampir didukung di mana-mana. Ketika Anda membuka file teks yang dikodekanUTF-8dari sistem lain, komputer Anda akan mendekode dan menampilkan karakter di dalamnya melalui nomor Unicode unik mereka. Ketika browser menerima data string yang dikodekan UTF-8dari jaringan, itu akan mendekode data ke string (menganggap browser dalam UTF-8pengkodean) dan menampilkan string.

Di python3, Anda dapat mengubah string dan byte string satu sama lain:

>>> print('中文'.encode('utf-8'))
b'\xe4\xb8\xad\xe6\x96\x87'
>>> print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))
中文 

Singkatnya, string adalah untuk ditampilkan kepada manusia untuk dibaca di komputer dan string byte adalah untuk disimpan ke disk dan transmisi data.

Sam Yang
sumber
1

Unicode adalah format yang disepakati untuk representasi biner dari karakter dan berbagai jenis format (misalnya huruf kecil / huruf besar, baris baru, carriage return), dan "hal-hal" lainnya (misalnya emoji). Komputer tidak kurang mampu menyimpan representasi unicode (serangkaian bit), baik dalam memori atau dalam file, daripada menyimpan representasi ascii (serangkaian bit yang berbeda), atau representasi lainnya (serangkaian bit ).

Agar komunikasi dapat terjadi, para pihak dalam komunikasi harus menyetujui perwakilan apa yang akan digunakan.

Karena unicode berusaha mewakili semua karakter yang mungkin (dan "hal-hal" lainnya) yang digunakan dalam komunikasi antar-manusia dan antar-komputer, ia memerlukan jumlah bit yang lebih besar untuk representasi banyak karakter (atau benda) daripada sistem representasi lain yang berusaha untuk mewakili serangkaian karakter / hal yang lebih terbatas. Untuk "menyederhanakan," dan mungkin untuk mengakomodasi penggunaan historis, representasi unicode hampir secara eksklusif dikonversi ke beberapa sistem representasi lainnya (misalnya ascii) untuk tujuan menyimpan karakter dalam file.

Hal ini tidak terjadi yang unicode tidak dapat digunakan untuk menyimpan karakter dalam file, atau mengirimkan mereka melalui setiap saluran komunikasi, hanya bahwa itu adalah tidak.

Istilah "string," tidak didefinisikan secara tepat. "String," dalam penggunaannya yang umum, mengacu pada serangkaian karakter / hal. Di komputer, karakter-karakter itu dapat disimpan dalam salah satu dari banyak representasi bit-demi-bit yang berbeda. "Byte string" adalah sekumpulan karakter yang disimpan menggunakan representasi yang menggunakan delapan bit (delapan bit disebut sebagai byte). Karena, akhir-akhir ini, komputer menggunakan sistem unicode (karakter diwakili oleh jumlah variabel byte) untuk menyimpan karakter dalam memori, dan string byte (karakter diwakili oleh byte tunggal) untuk menyimpan karakter ke file, konversi harus digunakan sebelum karakter diwakili dalam memori akan dipindahkan ke penyimpanan dalam file.

Gordon Shephard
sumber
0

Mari kita memiliki string satu karakter sederhana 'š'dan menyandikannya ke dalam urutan byte:

>>> 'š'.encode('utf-8')
b'\xc5\xa1'

Untuk tujuan contoh ini, mari kita tampilkan urutan byte dalam bentuk binernya:

>>> bin(int(b'\xc5\xa1'.hex(), 16))
'0b1100010110100001'

Sekarang umumnya tidak mungkin untuk memecahkan kode informasi kembali tanpa mengetahui bagaimana itu dikodekan. Hanya jika Anda tahu bahwa utf-8penyandian teks digunakan, Anda dapat mengikuti algoritme untuk mendekode utf-8 dan mendapatkan string asli:

11000101 10100001
   ^^^^^   ^^^^^^
   00101   100001

Anda dapat menampilkan nomor biner 101100001kembali sebagai string:

>>> chr(int('101100001', 2))
'š'
Jeyekomon
sumber
0

Bahasa Python termasuk strdan bytessebagai standar "Tipe Built-in". Dengan kata lain, mereka berdua kelas. Saya pikir tidak ada gunanya mencoba merasionalisasi mengapa Python diimplementasikan dengan cara ini.

Karena itu, strdan bytessangat mirip satu sama lain. Keduanya memiliki sebagian besar metode yang sama. Metode berikut unik untuk strkelas:

casefold
encode
format
format_map
isdecimal
isidentifier
isnumeric
isprintable

Metode berikut unik untuk byteskelas:

decode
fromhex
hex
lima puluh kartu
sumber