2015-12-01 11 views
6

現在私はPythonを学習しています。スロベニア語として、プログラムをテストするためによくUTF-8文字を使用します。通常はすべて正常に動作しますが、私が追い越すことができないキャッチが1つあります。私は特殊文字PythonでUTF-8文字列を反転する

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

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

を含む文字列を逆にしようとすると、それが失敗したファイルの先頭で宣言エンコード持っているにもかかわらず、これを修正する方法はありますか?

答えて

13

Python 2の文字列は、バイトの文字列であり、UTF-8エンコードされたテキストは1文字あたり複数のバイトを使用します。あなたの端末がUTF-8バイトを文字として解釈しているからといって、PythonがどのバイトがUTF-8の文字を形成しているかを知っているわけではありません。

あなたのバイト文字列は6バイト、2バイト毎フォーム1つの文字で構成されています:UTF-8の使用は、Unicode標準に文字が定義されている場所に依存し

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

しかし、どのように多くのバイト数。 ASCII文字(Unicode標準の最初の128文字)はそれぞれ1バイトしか必要とせず、多くの絵文字は4バイト必要です!

UTF-8オーダーではすべてです;上記バイト文字列を逆にするだけšō用)有効なUTF-8の配列であることがが起こるまでUTF-8標準に関しては、いくつかの意味不明で、その結果、バイトを反転するが、中間の4バイト:

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

バイト文字列を1文字で構成されるunicodeオブジェクトにデコードする必要があります。そのオブジェクトを逆にすると、あなたは右の結果を与える:

b = a.decode('utf8')[::-1] 
print b 
あなたが再びUTF-8に常に エンコードオブジェクトでき​​

:Unicodeで、あなたはまだ問題に実行することができます

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

注意をcombining charactersを使用すると、テキストを反転します。結合文字とテキストを逆にすると、むしろ、彼らはと結合文字の後よりも前で文字を組み合わせたものを置くので、彼らは代わりに間違った文字と結合します:

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

あなたがほとんどにUnicodeデータを変換することによってこれを避けることができ、その正規表現形式(1-codepoint形式の組み合わせを置き換えます)がありますが、文字列の反転ではうまく動作しない他のエキゾチックなUnicode文字がたくさんあります。

+0

文字列の反転と相互作用しない他のエキゾチックなUnicode文字がたくさんあります "_ means _"は文字列の反転でうまく機能しません "_または_"は文字列の反転の影響を受けません"_? – Piovezan

+0

@Piovezan:私は自分自身を100%確信しているわけではありません。私は*と一緒に行こうとしています*ストリングリバーサルでうまく動かない*。 –