web-dev-qa-db-ja.com

__repr __()関数の最良の出力タイプとエンコード方法は?

最近、私は__repr__()format()、およびエンコーディングに関して多くの問題を抱えています。 __repr__()の出力をエンコードするか、Unicode文字列にする必要がありますか? Pythonの__repr__()の結果に最適なエンコードはありますか?出力したいのは非ASCII文字です。

Python 2.xを使用していて、Python 3に簡単に適応できるコードを記述したい。したがって、プログラムは

_# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function  # The 'Hello' literal represents a Unicode object
_

ここに私を悩ませてきたいくつかの追加の問題があります、そして私はそれらを解決する解決策を探しています:

  1. UTF-8端末への印刷は機能するはずです(_sys.stdout.encoding_を_UTF-8_に設定していますが、他の場合も機能するのが最善です)。
  2. 出力をファイル(UTF-8でエンコード)にパイピングすると機能するはずです(この場合、_sys.stdout.encoding_はNoneです)。
  3. 多くの__repr__()関数の私のコードには現在多くのreturn ….encode('utf-8')があり、それは重いです。頑丈で軽いものはありますか?
  4. 場合によっては、return ('<{}>'.format(repr(x).decode('utf-8'))).encode('utf-8')のような醜い獣さえいます。つまり、オブジェクトの表現がデコードされ、フォーマット文字列に入れられてから、再エンコードされます。私はそのような複雑な変化を避けたいと思います。

これらのエンコーディングの質問に関してうまく動作する単純な__repr__()関数を作成するために、何をすることをお勧めしますか?

66
Eric O Lebigot

Python2では、__repr__(および__str__)は、Unicodeオブジェクトではなく、文字列オブジェクトを返す必要があります。 Python3では、状況が逆になり、__repr____str__はバイト(文字列)オブジェクトではなく、ユニコードオブジェクトを返す必要があります。

class Foo(object):
    def __repr__(self):
        return u'\N{WHITE SMILING FACE}' 

class Bar(object):
    def __repr__(self):
        return u'\N{WHITE SMILING FACE}'.encode('utf8')

repr(Bar())
# ☺
repr(Foo())
# UnicodeEncodeError: 'ascii' codec can't encode character u'\u263a' in position 0: ordinal not in range(128)

Python2では、実際には選択肢がありません。 __repr__の戻り値のエンコーディングを選択する必要があります。

ちなみに、 PrintFails wiki を読んだことがありますか?他の質問に直接答えることはできないかもしれませんが、特定のエラーが発生する理由を明らかにするのに役立つと思いました。


from __future__ import unicode_literalsを使用する場合、

'<{}>'.format(repr(x).decode('utf-8'))).encode('utf-8')

より簡単に次のように書くことができます

str('<{}>').format(repr(x))

strがシステム上でutf-8にエンコードされると仮定します。

from __future__ import unicode_literalsがない場合、式は次のように記述できます。

'<{}>'.format(repr(x))
41
unutbu

デコレータは__repr__の非互換性を適切な方法で管理できると思います。これが私が使うものです:

from __future__ import unicode_literals, print_function
import sys

def force_encoded_string_output(func):

    if sys.version_info.major < 3:

        def _func(*args, **kwargs):
            return func(*args, **kwargs).encode(sys.stdout.encoding or 'utf-8')

        return _func

    else:
        return func


class MyDummyClass(object):

    @force_encoded_string_output
    def __repr__(self):
        return 'My Dummy Class! \N{WHITE SMILING FACE}'
6
Titon

私は次のような関数を使用します:

def stdout_encode(u, default='UTF8'):
    if sys.stdout.encoding:
        return u.encode(sys.stdout.encoding)
    return u.encode(default)

それから私の__repr__関数は次のようになります。

def __repr__(self):
    return stdout_encode(u'<MyClass {0} {1}>'.format(self.abcd, self.efgh))
1
Buttons840