2015-12-01 23 views
6

Tôi hiện đang học Python và là người Slovenia tôi thường sử dụng các ký tự UTF-8 để kiểm tra các chương trình của mình. Thông thường mọi thứ đều hoạt động tốt, nhưng có một điều mà tôi không thể vượt qua. Mặc dù tôi đã mã hóa khai báo trên đầu tệp không thành công khi tôi cố gắng đảo ngược chuỗi chứa các ký tự đặc biệtPython đảo ngược chuỗi UTF-8

#-*- coding: utf-8 -*- 

a = "čšž" 
print a #prints čšž 
b = a[::-1] 
print b #prints �šō� instead of žšč 

Có cách nào để khắc phục điều đó không?

Trả lời

13

Chuỗi Python 2 là chuỗi byte và văn bản được mã hóa UTF-8 sử dụng nhiều byte cho mỗi ký tự. Chỉ vì thiết bị đầu cuối của bạn quản lý để diễn giải các byte UTF-8 như các ký tự, không có nghĩa là Python biết về byte nào tạo thành một ký tự UTF-8.

bytestring của bạn bao gồm 6 byte, mỗi byte hai hình thức một ký tự:

>>> a = "čšž" 
>>> a 
'\xc4\x8d\xc5\xa1\xc5\xbe' 

Tuy nhiên, có bao nhiêu byte UTF-8 sử dụng phụ thuộc vào nơi trong tiêu chuẩn Unicode nhân vật được xác định; Ký tự ASCII (128 ký tự đầu tiên trong tiêu chuẩn Unicode) chỉ cần 1 byte mỗi ký tự và nhiều biểu tượng cảm xúc cần 4 byte!

Trong đơn đặt hàng UTF-8 là mọi thứ; đảo ngược bytestring trên đảo ngược byte, dẫn đến một số vô nghia xa như tiêu chuẩn UTF-8 là có liên quan, nhưng giữa 4 byte chỉ xảy ra mới có giá trị UTF-8 chuỗi (ví šō):

>>> a[::-1] 
'\xbe\xc5\xa1\xc5\x8d\xc4' 
-----~~~~~~~~^^^^^^^^#### 
    |  š  ō  | 
    \     \ 
    invalid UTF8 byte opening UTF-8 byte missing a second byte 

Bạn phải giải mã chuỗi byte thành đối tượng unicode, bao gồm các ký tự đơn. Đảo ngược đối tượng cung cấp cho bạn kết quả ngay:

b = a.decode('utf8')[::-1] 
print b 

Bạn có thể luôn mã hóa đối tượng trở về UTF-8 một lần nữa:

b = a.decode('utf8')[::-1].encode('utf8') 

Lưu ý rằng trong Unicode, bạn vẫn có thể chạy vào các vấn đề khi đảo ngược văn bản, khi sử dụng combining characters. Đảo ngược văn bản với các nhân vật kết hợp đặt những cách kết hợp các nhân vật trước mặt chứ không phải sau khi nhân vật họ kết hợp với, vì vậy họ sẽ kết hợp với các ký tự sai thay vì:

>>> print u'e\u0301a' 
éa 
>>> print u'e\u0301a'[::-1] 
áe 

Bạn hầu như có thể tránh điều này bằng cách chuyển đổi các dữ liệu Unicode để nó dạng chuẩn hóa (thay thế các kết hợp với dạng 1-codepoint) nhưng có rất nhiều các ký tự Unicode lạ khác không hoạt động tốt với các đảo ngược chuỗi.

+0

Chỉ cần làm rõ: _ "nhưng có rất nhiều ký tự Unicode lạ khác không tương tác với đảo ngược chuỗi" _ means _ "không hoạt động tốt với chuỗi đảo ngược" _ hoặc _ "không bị ảnh hưởng bởi việc đảo ngược chuỗi "_? – Piovezan

+0

@ Piovezan: Tôi không chắc chắn 100% bản thân mình; Tôi sẽ với * không chơi tốt với đảo ngược chuỗi *. –