3

Unicodeの問題を処理しているときに、私はそれを見つけ、unicode(self)異なるself.__unicode__()動作をします。

#-*- coding:utf-8 -*-
import sys
import dis
class test():
    def __unicode__(self):
        s = u'中文'
        return s.encode('utf-8')

    def __str__(self):
        return self.__unicode__()
print dis.dis(test)
a = test()
print a

上記のコードは問題なく動作しますが、に変更self.__unicode__()するunicode(self)とエラーが表示されます。

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)

問題のあるコードは次のとおりです。

#-*- coding:utf-8 -*-
import sys
import dis
class test():
    def __unicode__(self):
        s = u'中文'
        return s.encode('utf-8')

    def __str__(self):
        return unicode(self)
print dis.dis(test)
a = test()
print a

Pythonがこれをどのように処理するかについて非常に興味があり、disモジュールを試しましたが、あまり多くの違いは見られませんでした。

Disassembly of __str__:
 12           0 LOAD_FAST                0 (self)
              3 LOAD_ATTR                0 (__unicode__)
              6 CALL_FUNCTION            0
              9 RETURN_VALUE   

VS

Disassembly of __str__:
 10           0 LOAD_GLOBAL              0 (unicode)
              3 LOAD_FAST                0 (self)
              6 CALL_FUNCTION            1
              9 RETURN_VALUE       
4

4 に答える 4

5

メソッドから戻りbytesます__unicode__

明確にするために:

In [18]: class Test(object):
    def __unicode__(self):
        return u'äö↓'.encode('utf-8')
    def __str__(self):
        return unicode(self)
   ....:     

In [19]: class Test2(object):
    def __unicode__(self):
        return u'äö↓'
    def __str__(self):
        return unicode(self)
   ....:     

In [20]: t = Test()

In [21]: t.__str__()
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
/home/dav1d/<ipython-input-21-e2650f29e6ea> in <module>()
----> 1 t.__str__()

/home/dav1d/<ipython-input-18-8bc639cbc442> in __str__(self)
      3         return u'äö↓'.encode('utf-8')
      4     def __str__(self):
----> 5         return unicode(self)
      6 

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

In [22]: unicode(t)
---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
/home/dav1d/<ipython-input-22-716c041af66e> in <module>()
----> 1 unicode(t)

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 0: ordinal not in range(128)

In [23]: t2 = Test2()

In [24]: t2.__str__()
Out[24]: u'\xe4\xf6\u2193'

In [25]: str(_) # _ = last result
---------------------------------------------------------------------------
UnicodeEncodeError                        Traceback (most recent call last)
/home/dav1d/<ipython-input-25-3a1a0b74e31d> in <module>()
----> 1 str(_) # _ = last result

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)'

In [26]: unicode(t2)
Out[26]: u'\xe4\xf6\u2193'

In [27]: class Test3(object):
def __unicode__(self):
    return u'äö↓'
def __str__(self):
    return unicode(self).encode('utf-8')
....:     

In [28]: t3 = Test3()

In [29]: t3.__unicode__()
Out[29]: u'\xe4\xf6\u2193'

In [30]: t3.__str__()
Out[30]: '\xc3\xa4\xc3\xb6\xe2\x86\x93'

In [31]: print t3
äö↓

In [32]: print unicode(t3)
äö↓

print aまたは、私の場合は、返されると予想されるesprint tを呼び出して返させて、動作しないようにエンコードしようとします。t.__str__bytesunicodeascii

簡単な修正:__unicode__Unicodeと__str__バイトを返しましょう。

于 2012-06-20T10:14:12.930 に答える
3
s = u'中文'
return s.encode('utf-8')

これは、非Unicodeのバイト文字列を返します。それencodeがやっていることです。utf-8は、魔法のようにデータをUnicodeに変換するものではありません。どちらかといえば、それは反対です-バイト(データ、多かれ少なかれ)でUnicode(抽象化)を表す方法。

ここで少し用語が必要です。エンコードとは、ある種のエンコードを使用して、Unicode文字列を取得し、それを表すバイト文字列を作成することです。デコードするのは逆です。バイト文字列(Unicode文字列をエンコードすると思われる)を取得し、指定されたエンコードを使用してそれをUnicode文字列として解釈します。

バイト文字列にエンコードしてから同じエンコードを使用してデコードすると、元のUnicodeが返されます。

utf-8可能なエンコーディングの1つです。たくさんあります。

UnicodeDecodeErrorを呼び出すと、Pythonがを報告することがありますencode。なんで?あなたがencodeバイト文字列をしようとしているからです。このプロセスの適切な入力はUnicode文字列であるため、Pythonはdecode最初にバイト文字列をUnicodeに変換しようとします。ただし、使用するコーデックがわからないため、を想定していますascii。このコーデックは、あらゆる種類のデータを受信できる環境で最も安全な選択です。これは、128を超えるバイトのエラーを報告するだけであり、さまざまな8ビットエンコーディングで数え切れないほどのさまざまな方法で処理されます。é( MacからPCに、またはその逆のような文字を含むWordファイルをインポートしようとしたことを覚えていますか?プラットフォームの組み込みエンコーディングが異なっていたため、他のコンピューターに他の奇妙な記号が表示されます。)

さらに複雑なことに、Python 2ではencode/decodeメカニズムを使用して、Unicodeの解釈とは関係のない他の優れた機能を実装しています。たとえば、Base64エンコーダーと、文字列エスケープシーケンスを自動的に処理するものがあります(つまり、バックスラッシュの後に文字「t」が続くタブに変更されます)。これらのいくつかはバイト文字列からバイト文字列へ、またはUnicodeからUnicodeへ「エンコード」または「デコード」します。

ちなみに、これはすべて完全に異なって動作します-はるかに明確に、私見-Python 3では)

同様に__unicode__、バイト文字列を返す場合(スタイルの問題として、これはすべきではありません)、Pythonの組み込み関数は自動的にそれを;unicode()としてデコードします。asciiそして__str__、Unicode文字列を返すとき(これもまたそうすべきではありません)、str()それをとしてエンコードしasciiます。これは舞台裏で発生します。コードでは制御できません。ただし、修正__unicode____str__て、想定されていることを実行することはできます。

(実際には、2番目のパラメーターを渡すことで、のエンコードをオーバーライドできunicodeます。ただし、ここでは、Unicode文字列が既に返されているはずなので、これは間違った解決策です__unicode__strエンコードパラメーターを受け取らないので、次のようになります。運が悪かった。)

これで、問題を解決できます。

問題:__unicode__Unicode文字列を返したいのですが、そのエンコードされたバージョンを返したいのですu'中文'__str__utf-8

解決策:その文字列を直接で返し__unicode__、エンコードを明示的に__str__:で行います。

class test():
    def __unicode__(self):
        return u'中文'

    def __str__(self):
        return unicode(self).encode('utf-8')
于 2012-06-20T10:38:01.047 に答える
0

Pythonオブジェクトを呼び出すとunicode、出力はunicodeメソッドに渡す引数のUnicode表現になります。

使用するエンコーディングを指定していないため、ASCIIのみを使用して引数を表すことができないというエラーが発生します。

を使用する__unicode__場合は、utf-8を使用してその文字列をエンコードする必要があることを指定しています。これは正しく、問題なく発生します。

unicode次のように、メソッドの2番目のパラメーターとして目的のエンコーディングを使用できます。

unicode( str, "utf-8" )

そして、それはあなたの__unicode__方法がするのと同じように働くはずです。

于 2012-06-20T10:19:02.917 に答える
0

特別なメソッドを定義するときに__unicode__、使用するエンコーディングを指定しました。単に呼び出すunicodeときはエンコーディングを指定しなかったため、Pythonはデフォルトの「ascii」を使用しました。

ところで、__str__ユニコードではなく、バイトの文字列を返す必要があります。__unicode__バイト文字列ではなく、Unicodeを返す必要があります。したがって、このコードは逆方向です。Unicodeを返さないため、Pythonはおそらくデフォルトのエンコーディングを使用して変換しようとしています。

于 2012-06-20T10:19:30.123 に答える