クラスオブジェクトのカスタム文字列表現を作成する方法


202

このクラスを考えてみましょう:

class foo(object):
    pass

デフォルトの文字列表現は次のようになります。

>>> str(foo)
"<class '__main__.foo'>"

これをカスタム文字列にするにはどうすればよいですか?

回答:


272

クラスのメタクラスに実装する__str__()__repr__()、そのクラスに入れます。

class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(object):
  __metaclass__ = MC

print C

__str__読みやすい文字列化を意味する場合に使用し__repr__、明確な表現に使用します。


2
ある種のクラスデコレータを作成したいので、クラスごとにメタクラスを記述しなくても、クラスのカスタム文字列表現を簡単に設定できます。私はPythonのメタクラスにあまり詳しくないので、そこでポインタを教えてもらえますか?
ビョルンPollex

残念ながら、これはクラスデコレータでは実行できません。クラスを定義するときに設定する必要があります。
Ignacio Vazquez-Abrams

10
@ Space_C0wb0y:あなたのような文字列を追加することができ_representation、クラスのボディにとreturn self._representationして__repr__()メタクラスの方法。
Sven Marnach、2011

@BjörnPollexデコレータでこれをプルできるかもしれませんが、言語の多くの微妙な点に苦労する必要があると思います。そして、そうしたとしても、デフォルト__repr__を使用してを表現したくないので、何らかの方法でメタクラスを使用する必要がありますC_representationメンバーを持つ代わりに、適切なメタクラスを生成するメタクラスファクトリを作成する__repr__こともできます(これを頻繁に使用している場合、これは良いことです)。
16


22
class foo(object):
    def __str__(self):
        return "representation"
    def __unicode__(self):
        return u"representation"

10
これにより、instancesクラス自体ではなく、クラスの文字列表現が変更されます。
タウラン

申し訳ありませんが、投稿の2番目の部分は表示されません。上記の方法を使用します。
Andrey Gubarev、2011

6
@RobertSiemerなんで?彼の回答は特にOPの質問を対象としているわけではありませんが、それでも役に立ちます。それは私を助けました。そして一目で、インスタンスの実装を求める質問はありません。したがって、おそらく最初にこのページにアクセスします。
-akinuri

14

デフォルトの実装では、それが定義されていないときに呼び出されるため、どちら__repr__かを選択する必要がある場合、または__str__最初のものに進む必要がある場合。__str____repr__

カスタムVector3の例:

class Vector3(object):
    def __init__(self, args):
        self.x = args[0]
        self.y = args[1]
        self.z = args[2]

    def __repr__(self):
        return "Vector3([{0},{1},{2}])".format(self.x, self.y, self.z)

    def __str__(self):
        return "x: {0}, y: {1}, z: {2}".format(self.x, self.y, self.z)

この例でreprは、直接消費/実行できる文字列を再び返しますがstr、デバッグ出力としてはより便利です。

v = Vector3([1,2,3])
print repr(v)    #Vector3([1,2,3])
print str(v)     #x:1, y:2, z:3

1
__repr__vs に関するあなたの__str__主張は正しいですが、これはインスタンスではなくクラスオブジェクトに関する実際の質問には答えません。
ビョルンPollex

フィードバックをありがとう、完全に監視しました。私の答えを復習させてください。
user1767754 2018年

reprとstrの実装は入れ替えられていると思います。
jspencer 2018年

4

イグナシオ・バスケス=エイブラムスの承認された答えはまったく正しい。ただし、これはPython 2世代のものです。現在のPython 3の更新は次のようになります。

class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(object, metaclass=MC):
    pass

print(C)

Python 2とPython 3の両方で実行されるコードが必要な場合は、6つのモジュールで対応できます。

from __future__ import print_function
from six import with_metaclass

class MC(type):
  def __repr__(self):
    return 'Wahaha!'

class C(with_metaclass(MC)):
    pass

print(C)

最後に、カスタム静的reprが必要なクラスが1つある場合は、上記のクラスベースのアプローチが適切に機能します。しかし、複数ある場合は、MCfor と同様のメタクラスを生成する必要があり、面倒になる可能性があります。その場合、メタプログラミングをさらに一歩進めてメタクラスファクトリを作成すると、状況が少しわかりやすくなります。

from __future__ import print_function
from six import with_metaclass

def custom_class_repr(name):
    """
    Factory that returns custom metaclass with a class ``__repr__`` that
    returns ``name``.
    """
    return type('whatever', (type,), {'__repr__': lambda self: name})

class C(with_metaclass(custom_class_repr('Wahaha!'))): pass

class D(with_metaclass(custom_class_repr('Booyah!'))): pass

class E(with_metaclass(custom_class_repr('Gotcha!'))): pass

print(C, D, E)

プリント:

Wahaha! Booyah! Gotcha!

メタプログラミングは、通常、日常的に必要とするものではありませんが、必要なときに、まさにその場にいます。


0

すべての細かい答え、装飾付きの私のバージョンに追加するだけです:

from __future__ import print_function
import six

def classrep(rep):
    def decorate(cls):
        class RepMetaclass(type):
            def __repr__(self):
                return rep

        class Decorated(six.with_metaclass(RepMetaclass, cls)):
            pass

        return Decorated
    return decorate


@classrep("Wahaha!")
class C(object):
    pass

print(C)

stdout:

Wahaha!

欠点:

  1. Cスーパークラスなしでは宣言できません(no class C:
  2. Cインスタンスは奇妙な派生のインスタンスになる__repr__ため、インスタンスにもを追加することをお勧めします。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.