Câu trả lời:
Giả sử Python 3 (trong Python 2, sự khác biệt này được xác định rõ hơn một chút) - một chuỗi là một chuỗi các ký tự, tức là các điểm mã unicode ; đây là một khái niệm trừu tượng và không thể được lưu trữ trực tiếp trên đĩa. Chuỗi byte là một chuỗi, không có gì đáng ngạc nhiên, byte - những thứ có thể được lưu trữ trên đĩa. Ánh xạ giữa chúng là một mã hóa - có khá nhiều trong số này (và có thể có rất nhiều thứ có thể) - và bạn cần biết áp dụng trong trường hợp cụ thể để thực hiện chuyển đổi, vì một mã hóa khác có thể ánh xạ các byte giống nhau đến một chuỗi khác:
>>> 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ς'
Khi bạn biết nên sử dụng cái nào, bạn có thể sử dụng .decode()
phương thức của chuỗi byte để có được chuỗi ký tự đúng từ nó như trên. Để đầy đủ, .encode()
phương thức của một chuỗi ký tự đi theo cách ngược lại:
>>> 'τoρνoς'.encode('utf-8')
b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'
str
các đối tượng Python 3 không thể truy cập hoặc có liên quan từ phía Python; cấu trúc dữ liệu chỉ là một chuỗi các điểm mã. Theo PEP 393 , mã hóa nội bộ chính xác là một trong số Latin-1, UCS2 hoặc UCS4 và đại diện utf-8 có thể được lưu trữ sau khi được yêu cầu lần đầu, nhưng ngay cả mã C cũng không được khuyến khích dựa vào các chi tiết nội bộ này.
Thứ duy nhất mà máy tính có thể lưu trữ là byte.
Để lưu trữ bất cứ thứ gì trong máy tính, trước tiên bạn phải mã hóa nó, tức là chuyển đổi nó thành byte. Ví dụ:
MP3
, WAV
vvPNG
, JPEG
vvASCII
, UTF-8
vvMP3
, WAV
, PNG
, JPEG
, ASCII
Và UTF-8
là ví dụ về mã hóa . Mã hóa là một định dạng để thể hiện âm thanh, hình ảnh, văn bản, vv theo byte.
Trong Python, một chuỗi byte chỉ là: một chuỗi các byte. Nó không phải là con người có thể đọc được. Trong mui xe, mọi thứ phải được chuyển đổi thành một chuỗi byte trước khi nó có thể được lưu trữ trong máy tính.
Mặt khác, một chuỗi ký tự, thường chỉ được gọi là "chuỗi", là một chuỗi các ký tự. Nó là con người có thể đọc được. Một chuỗi ký tự không thể được lưu trữ trực tiếp trong máy tính, nó phải được mã hóa trước tiên (được chuyển đổi thành chuỗi byte). Có nhiều mã hóa thông qua đó một chuỗi ký tự có thể được chuyển đổi thành một chuỗi byte, chẳng hạn như ASCII
và UTF-8
.
'I am a string'.encode('ASCII')
Mã Python ở trên sẽ mã hóa chuỗi 'I am a string'
bằng mã hóa ASCII
. Kết quả của đoạn mã trên sẽ là một chuỗi byte. Nếu bạn in nó, Python sẽ đại diện cho nó là b'I am a string'
. Tuy nhiên, hãy nhớ rằng các chuỗi byte không thể đọc được bằng con người , chỉ là Python giải mã chúng từ ASCII
khi bạn in chúng. Trong Python, một chuỗi byte được biểu thị bằng a b
, theo sau là ASCII
biểu diễn của chuỗi byte .
Một chuỗi byte có thể được giải mã trở lại thành một chuỗi ký tự, nếu bạn biết mã hóa được sử dụng để mã hóa nó.
b'I am a string'.decode('ASCII')
Đoạn mã trên sẽ trả về chuỗi gốc 'I am a string'
.
Mã hóa và giải mã là các hoạt động nghịch đảo. Tất cả mọi thứ phải được mã hóa trước khi nó có thể được ghi vào đĩa và nó phải được giải mã trước khi con người có thể đọc được.
Lưu ý: Tôi sẽ giải thích thêm câu trả lời của tôi cho Python 3 vì thời gian kết thúc của Python 2 rất gần.
Trong Python 3
bytes
bao gồm các chuỗi các giá trị không dấu 8 bit, trong khi str
bao gồm các chuỗi các điểm mã Unicode đại diện cho các ký tự văn bản từ ngôn ngữ của con người.
>>> # 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
Mặc dù bytes
và str
dường như hoạt động theo cùng một cách, các thể hiện của chúng không tương thích với nhau, nghĩa là, bytes
và các str
thể hiện không thể được sử dụng cùng với các toán tử như >
và +
. Ngoài ra, hãy nhớ rằng so sánh bytes
và các str
trường hợp cho sự bình đẳng, tức là sử dụng ==
, sẽ luôn luôn đánh giá False
ngay cả khi chúng chứa chính xác các ký tự.
>>> # 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
Một vấn đề khác khi xử lý bytes
và str
có mặt khi làm việc với các tệp được trả về bằng open
hàm tích hợp. Một mặt, nếu bạn muốn đọc hoặc ghi dữ liệu nhị phân vào / từ một tệp, luôn mở tệp bằng chế độ nhị phân như 'rb' hoặc 'wb'. Mặt khác, nếu bạn muốn đọc hoặc ghi dữ liệu Unicode đến / từ một tệp, hãy lưu ý mã hóa mặc định của máy tính của bạn, vì vậy nếu cần, hãy chuyển encoding
tham số để tránh gây bất ngờ.
Trong Python 2
str
bao gồm các chuỗi các giá trị 8 bit, trong khi unicode
bao gồm các chuỗi các ký tự Unicode. Một điều cần lưu ý là str
và unicode
có thể được sử dụng cùng với các toán tử nếu str
chỉ bao gồm các ký tự ASCI 7 bit.
Có thể hữu ích khi sử dụng các hàm trợ giúp để chuyển đổi giữa str
và unicode
trong Python 2 và giữa bytes
và str
trong Python 3.
Từ Unicode là gì :
Về cơ bản, máy tính chỉ cần đối phó với những con số. Họ lưu trữ các chữ cái và các ký tự khác bằng cách gán một số cho mỗi cái.
......
Unicode cung cấp một số duy nhất cho mỗi ký tự, bất kể nền tảng nào, bất kể chương trình nào, bất kể ngôn ngữ nào.
Vì vậy, khi một máy tính đại diện cho một chuỗi, nó sẽ tìm thấy các ký tự được lưu trữ trong máy tính của chuỗi thông qua số Unicode duy nhất của chúng và các số liệu này được lưu trữ trong bộ nhớ. Nhưng bạn không thể trực tiếp ghi chuỗi vào đĩa hoặc truyền chuỗi trên mạng thông qua số Unicode duy nhất của chúng vì những số liệu này chỉ là số thập phân đơn giản. Bạn nên mã hóa chuỗi thành chuỗi byte, chẳng hạn như UTF-8
. UTF-8
là một mã hóa ký tự có khả năng mã hóa tất cả các ký tự có thể và nó lưu trữ các ký tự dưới dạng byte (trông giống như thế này ). Vì vậy, chuỗi được mã hóa có thể được sử dụng ở mọi nơi vì UTF-8
gần như được hỗ trợ ở mọi nơi. Khi bạn mở một tệp văn bản được mã hóa trongUTF-8
từ các hệ thống khác, máy tính của bạn sẽ giải mã nó và hiển thị các ký tự trong đó thông qua số Unicode duy nhất của chúng. Khi một trình duyệt nhận dữ liệu chuỗi được mã hóa UTF-8
từ mạng, nó sẽ giải mã dữ liệu thành chuỗi (giả sử trình duyệt UTF-8
mã hóa) và hiển thị chuỗi.
Trong python3, bạn có thể chuyển đổi chuỗi và chuỗi byte sang nhau:
>>> print('中文'.encode('utf-8'))
b'\xe4\xb8\xad\xe6\x96\x87'
>>> print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))
中文
Trong một từ, chuỗi là để hiển thị cho con người để đọc trên máy tính và chuỗi byte là để lưu trữ vào đĩa và truyền dữ liệu.
Unicode là định dạng được thỏa thuận cho biểu diễn nhị phân của các ký tự và các loại định dạng khác nhau (ví dụ: chữ thường / chữ in hoa, dòng mới, trả lại vận chuyển) và các "thứ" khác (ví dụ: biểu tượng cảm xúc). Một máy tính không kém khả năng lưu trữ một đại diện unicode (một chuỗi bit), cho dù trong bộ nhớ hoặc trong một tệp, so với việc lưu trữ một đại diện ascii (một chuỗi bit khác nhau) hoặc bất kỳ đại diện nào khác (chuỗi bit ).
Để giao tiếp diễn ra, các bên tham gia giao tiếp phải thống nhất về việc đại diện nào sẽ được sử dụng.
Bởi vì unicode tìm cách đại diện cho tất cả các ký tự có thể (và các "thứ" khác) được sử dụng trong giao tiếp giữa người và máy tính, nên nó đòi hỏi số bit lớn hơn để thể hiện nhiều ký tự (hoặc vật) so với các hệ thống biểu diễn khác tìm cách đại diện cho một tập hợp các nhân vật / thứ giới hạn hơn. Để "đơn giản hóa" và có lẽ để phù hợp với việc sử dụng lịch sử, biểu diễn unicode gần như được chuyển đổi thành một số hệ thống biểu diễn khác (ví dụ ascii) cho mục đích lưu trữ các ký tự trong tệp.
Đây không phải là trường hợp unicode không thể được sử dụng để lưu trữ các ký tự trong tệp hoặc truyền chúng qua bất kỳ kênh liên lạc nào , đơn giản là không phải vậy.
Thuật ngữ "chuỗi" không được xác định chính xác. "Chuỗi", theo cách sử dụng phổ biến của nó, đề cập đến một tập hợp các ký tự / vật. Trong máy tính, các ký tự đó có thể được lưu trữ trong bất kỳ một trong nhiều cách biểu diễn từng bit khác nhau. "Chuỗi byte" là một tập hợp các ký tự được lưu trữ bằng cách sử dụng một biểu diễn sử dụng tám bit (tám bit được gọi là một byte). Vì ngày nay, máy tính sử dụng hệ thống unicode (ký tự được biểu thị bằng số byte thay đổi) để lưu trữ các ký tự trong bộ nhớ và chuỗi byte (ký tự được biểu thị bằng byte đơn) để lưu trữ các ký tự vào tệp, phải sử dụng chuyển đổi trước khi ký tự được biểu thị trong bộ nhớ sẽ được chuyển vào lưu trữ trong các tập tin.
Chúng ta hãy có một chuỗi một ký tự đơn giản 'š'
và mã hóa nó thành một chuỗi byte:
>>> 'š'.encode('utf-8')
b'\xc5\xa1'
Với mục đích của ví dụ này, hãy hiển thị chuỗi byte ở dạng nhị phân của nó:
>>> bin(int(b'\xc5\xa1'.hex(), 16))
'0b1100010110100001'
Bây giờ nói chung không thể giải mã thông tin trở lại mà không biết làm thế nào nó được mã hóa. Chỉ khi bạn biết rằng utf-8
mã hóa văn bản đã được sử dụng, bạn có thể theo thuật toán để giải mã utf-8 và có được chuỗi gốc:
11000101 10100001
^^^^^ ^^^^^^
00101 100001
Bạn có thể hiển thị số nhị phân 101100001
trở lại dưới dạng chuỗi:
>>> chr(int('101100001', 2))
'š'
Các ngôn ngữ Python bao gồm str
và bytes
dưới dạng "Các loại tích hợp" tiêu chuẩn. Nói cách khác, cả hai đều là lớp. Tôi không nghĩ rằng đáng để cố gắng hợp lý hóa lý do tại sao Python được thực hiện theo cách này.
Phải nói rằng, str
và bytes
rất giống nhau. Cả hai đều chia sẻ hầu hết các phương pháp giống nhau. Các phương thức sau là duy nhất cho str
lớp:
casefold
encode
format
format_map
isdecimal
isidentifier
isnumeric
isprintable
Các phương thức sau là duy nhất cho bytes
lớp:
decode
fromhex
hex
str
loại giống nhưbytes
loại; câu trả lời này tương đương so sánhunicode
loại (không tồn tại trong Python 3) vớistr
loại.