2012-04-08 50 views
27

Bạn có thể giải thích chi tiết sự khác nhau giữa chuỗi byte và chuỗi Unicode trong Python hay không. Tôi đã đọc this:chuỗi byte so với chuỗi unicode. Python

đang Byte chỉ đơn giản là mã nguồn được chuyển đổi thành các mảng byte

Liệu nó có nghĩa là Python có định dạng mã hóa/mã hóa riêng của mình? Hay nó sử dụng các thiết lập hệ điều hành? Tôi không hiểu. Bạn có thể giải thích? Cảm ơn bạn!

+8

coolinterview.com trông giống như một nguồn thông tin khủng khiếp. Tôi sẽ không dựa vào nó. – bames53

+6

"Byte code" thường đề cập đến một cái gì đó hoàn toàn khác nhau, http://docs.python.org/glossary.html "Mã nguồn Python được biên dịch thành bytecode, biểu diễn bên trong của một chương trình Python trong trình thông dịch CPython. được lưu trong tệp .pyc và .pyo " – dbr

+0

+1 nhận xét của dbr. Bytecode là một chi tiết thực hiện CPython bên trong không liên quan đến Unicode và bạn có thể không phải lo lắng về nó. – bobince

Trả lời

28

Không có trăn không sử dụng mã hóa riêng. Nó sẽ sử dụng bất kỳ mã hóa nào mà nó có quyền truy cập và bạn chỉ định. Một ký tự trong một str đại diện cho một ký tự unicode. Tuy nhiên để đại diện cho hơn 256 ký tự, mã hóa unicode riêng lẻ sử dụng nhiều hơn một byte cho mỗi ký tự để biểu thị nhiều ký tự. bytearray đối tượng cung cấp cho bạn quyền truy cập vào các byte underlaying. Các đối tượng str có phương thức encode lấy một chuỗi biểu thị mã hóa và trả về đối tượng bytearray đại diện cho chuỗi trong mã hóa đó. Các đối tượng bytearray có phương thức decode lấy một chuỗi biểu thị mã hóa và trả về str kết quả từ việc giải thích bytearray dưới dạng chuỗi được mã hóa trong mã hóa đã cho. Đây là một ví dụ.

>>> a = "αά".encode('utf-8') 
>>> a 
b'\xce\xb1\xce\xac' 
>>> a.decode('utf-8') 
'αά' 

Chúng ta có thể thấy rằng UTF-8 được sử dụng bốn byte, \ xce, \ xb1, \ xce, và \ xac để đại diện cho hai nhân vật. Sau bài báo Spolsky mà Ignacio Vazquez-Abrams gọi, tôi sẽ đọc số Python Unicode Howto.

+16

Có lẽ bạn nên đề cập rằng mã này là dành cho Python 3. – ovgolovin

+2

Bạn có nghĩa là các đối tượng 'byte', không có' bytearray': trên thực tế, 'type (" é ".encode ('UTF-8'))' là 'byte' , không phải 'bytearray'. – EOL

+0

Phiên bản Python nào? 2.7 báo cáo nó là ' '. –

19

Đây là một lời giải thích đơn giản chỉ áp dụng cho Python 3. Tôi hy vọng rằng đến từ một người cư sĩ, nó sẽ giúp làm sáng tỏ một số sự nhầm lẫn cho người hoàn toàn không được khởi xướng. Nếu có bất kỳ sự thiếu chính xác về kỹ thuật, xin hãy tha thứ cho tôi và cảm thấy tự do để chỉ ra nó.

Giả sử bạn tạo một chuỗi sử dụng Python 3 theo cách thông thường:

stringobject = 'ant' 

stringobject sẽ là một chuỗi unicode.

Chuỗi unicode được tạo thành từ các ký tự unicode. Trong các số stringobject ở trên, các ký tự unicode là các chữ cái riêng lẻ, ví dụ: a, n, t

Mỗi ký tự unicode được gán một điểm mã, có thể được biểu diễn dưới dạng một chuỗi các chữ số hex (một chữ số hex có thể nhận 16 giá trị, từ 0-9 và A-F). Ví dụ: chữ cái 'a' tương đương với '\u0091' và 'kiến' tương đương với '\u0061\u006E\u0074'.

Vì vậy, bạn sẽ thấy rằng nếu bạn gõ vào,

stringobject = '\u0061\u006E\u0074' 
stringobject 

Bạn cũng sẽ nhận được đầu ra 'ant'.

Bây giờ, unicode được chuyển đổi thành byte, trong quá trình được gọi là mã hóa. Quá trình đảo ngược của chuyển đổi byte thành unicode được gọi là giải mã .

Điều này được thực hiện như thế nào? Vì mỗi chữ số hex có thể có 16 giá trị khác nhau, nó có thể được phản ánh trong chuỗi nhị phân 4 bit (ví dụ: chữ số thập phân 0 có thể được biểu diễn dưới dạng nhị phân là 0000, chữ số hex 1 có thể được biểu diễn bằng 0001 và vv). Nếu một ký tự unicode có một điểm mã gồm bốn chữ số hex, nó sẽ cần một chuỗi nhị phân 16 bit để mã hóa nó.

Hệ thống mã hóa khác nhau chỉ định các quy tắc khác nhau để chuyển đổi unicode thành bit. Quan trọng nhất, mã hóa khác nhau về số bit mà chúng sử dụng để biểu thị từng ký tự unicode.

Ví dụ, hệ thống mã hóa ASCII chỉ sử dụng 8 bit (1 byte) cho mỗi ký tự. Do đó, nó chỉ có thể mã hóa các ký tự unicode với các điểm mã lên đến hai chữ số thập phân dài (tức là 256 ký tự unicode khác nhau). Hệ thống mã hóa UTF-8 sử dụng 8 đến 32 bit (1 đến 4 byte) cho mỗi ký tự, vì vậy nó có thể mã hóa các ký tự unicode với các điểm mã lên đến 8 chữ số thập phân, tức là mọi thứ.

Chạy đoạn mã sau:

byteobject = stringobject.encode('utf-8') 
byteobject, type(byteobject) 

chuyển đổi một chuỗi unicode vào một chuỗi byte bằng cách sử dụng hệ thống mã hóa utf-8, và trả b'ant', bytes'. Lưu ý rằng nếu bạn sử dụng 'ASCII' làm hệ thống mã hóa, bạn sẽ không gặp bất kỳ vấn đề gì vì tất cả các điểm mã trong 'ant' có thể được biểu diễn bằng 1 byte. Nhưng nếu bạn có một chuỗi unicode chứa các ký tự có mã điểm dài hơn hai chữ số thập phân, bạn sẽ nhận được một UnicodeEncodeError.

Tương tự,

stringobject = byteobject.decode('utf-8') 
stringobject, type(stringobject) 

mang đến cho bạn 'ant', str.

+0

(1) Nói chung, một ký tự do người dùng nhận thức như 'g̈' có thể tương ứng với một số điểm mã Unicode (U + 0067 U + 0308 trong trường hợp này). (2) mã hóa một codepoint Unicode có thể không liên quan đến số của nó, mã hóa 8 bit có thể đại diện cho ~ 0x100 ký tự, không nhất thiết phải tất cả các ký tự này * liên tiếp * (không cần thiết rằng * "mã điểm bao gồm bốn chữ số hex, nó sẽ cần một chuỗi nhị phân 16 bit để mã hóa nó "* - nó không có ý nghĩa để nói về kích thước cần thiết để mã hóa một điểm duy nhất - chỉ một tập hợp các ký tự áp đặt các hạn chế) – jfs

+0

Cảm ơn bạn. Lời giải thích tốt nhất mà tôi đã đọc. – parsecer