2009-08-12 4 views
0

組み込み関数__repr____str__は基本定義に重要な違いがあるようです。__str __()は舞台裏でdecode()メソッドを呼び出しますか?

>>> t2 = u'\u0131\u015f\u0131k' 
>>> print t2 
ışık 
>>> t2 
Out[0]: u'\u0131\u015f\u0131k' 

t2.decodet2は、Unicode文字列であるため、エラーが発生します。問題なく

>>> t2.__str__() 
------------------------------------------------------------ 
Traceback (most recent call last): 
    File "<ipython console>", line 1, in <module> 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordin 
al not in range(128) 

しかし__repr__作品:

>>> t2.__repr__() 
Out[0]: "u'\\u0131\\u015f\\u0131k'" 

はなぜ__str__は適切__repr__仕事に対し、エラーが発生するのでしょうか?decode()関数が呼び出されているかのように

>>> enc = 'utf-8' 
>>> t2.decode(enc) 
------------------------------------------------------------ 
Traceback (most recent call last): 
    File "<ipython console>", line 1, in <module> 
    File "C:\java\python\Python25\Lib\encodings\utf_8.py", line 16, in decode 
    return codecs.utf_8_decode(input, errors, True) 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordin 
al not in range(128) 

__str__でエラーが発生しますか

この小さな違いは、私が取り組んでいる1つのdjangoアプリケーションにバグを引き起こすようです。

答えて

7

基本的に、__str__はASCII文字列のみを出力できます。 t2にはASCIIコードの上にUnicodeコードポイントが含まれているため、文字列で表現することはできません。一方、__repr__は、オブジェクトを再作成するために必要なPythonコードを出力しようとします。 repr(t2)の出力(この構文はt2.__repr_()よりも優先されます)は、まさに最初の行でt2をupに設定したものです。すべてのascii値ですが、strからの出力は[chr(0x0131)、chr(0x015f)]にしようとしていますが、reprの結果はおおよそ[​​'\'、 'u'、 '0' 、chr(0x0131)、 'k']、そのほとんどはPython文字列で許容される文字の範囲を超えています。一般に、djangoアプリケーションを扱う場合は、__unicode__をすべて使用し、__str__には絶対に触れないでください。

詳細情報はthe django documentation on stringsです。

5

一般に、str.__unicode__()またはunicode.__str__()を呼び出すことは、バイトを安全にUnicode文字ポイントに変換することができず、その逆もありません。例外はASCII値で、通常はすべてのシングルバイトエンコーディングで同じです。問題は、変換に間違った方法を使用していることです。 strunicodeを変換するには

、あなたがencode()を使用する必要があります。

>>> t1 = u"\u0131\u015f\u0131k" 
>>> t1.encode("utf-8") 
'\xc4\xb1\xc5\x9f\xc4\xb1k' 

unicodestrを変換するには、decode()を使用します。

>>> t2 = '\xc4\xb1\xc5\x9f\xc4\xb1k' 
>>> t2.decode("utf-8") 
u'\u0131\u015f\u0131k' 
2

ジョンの良い答えに支援のビットを追加するには:

2つの方法の名前を理解するにはエンコード()デコード()は、あなただけのPythonが参照形式にあるように、フォームU「...」のUnicode文字列を考慮することを確認する必要があります。 を参照フォーマットから別のフォーマット(例:utf-8)にエンコードし、をデコードして参照フォーマットにします。ユニコード形式は常に「本物」とみなされます:-)。

0

Python 3では、unicodeがデフォルトであり、__str__()は常にUnicodeを与える必要があることに注意してください。

関連する問題