このクラスを考えてみましょう:
class foo(object):
pass
デフォルトの文字列表現は次のようになります。
>>> str(foo)
"<class '__main__.foo'>"
これをカスタム文字列にするにはどうすればよいですか?
このクラスを考えてみましょう:
class foo(object):
pass
デフォルトの文字列表現は次のようになります。
>>> str(foo)
"<class '__main__.foo'>"
これをカスタム文字列にするにはどうすればよいですか?
回答:
クラスのメタクラスに実装する__str__()
か__repr__()
、そのクラスに入れます。
class MC(type):
def __repr__(self):
return 'Wahaha!'
class C(object):
__metaclass__ = MC
print C
__str__
読みやすい文字列化を意味する場合に使用し__repr__
、明確な表現に使用します。
_representation
、クラスのボディにとreturn self._representation
して__repr__()
メタクラスの方法。
__repr__
を使用してを表現したくないので、何らかの方法でメタクラスを使用する必要がありますC
。_representation
メンバーを持つ代わりに、適切なメタクラスを生成するメタクラスファクトリを作成する__repr__
こともできます(これを頻繁に使用している場合、これは良いことです)。
class foo(object):
def __str__(self):
return "representation"
def __unicode__(self):
return u"representation"
instances
クラス自体ではなく、クラスの文字列表現が変更されます。
デフォルトの実装では、それが定義されていないときに呼び出されるため、どちら__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
__repr__
vs に関するあなたの__str__
主張は正しいですが、これはインスタンスではなくクラスオブジェクトに関する実際の質問には答えません。
イグナシオ・バスケス=エイブラムスの承認された答えはまったく正しい。ただし、これは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つある場合は、上記のクラスベースのアプローチが適切に機能します。しかし、複数ある場合は、MC
for と同様のメタクラスを生成する必要があり、面倒になる可能性があります。その場合、メタプログラミングをさらに一歩進めてメタクラスファクトリを作成すると、状況が少しわかりやすくなります。
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!
メタプログラミングは、通常、日常的に必要とするものではありませんが、必要なときに、まさにその場にいます。
すべての細かい答え、装飾付きの私のバージョンに追加するだけです:
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!
欠点:
C
スーパークラスなしでは宣言できません(no class C:
)C
インスタンスは奇妙な派生のインスタンスになる__repr__
ため、インスタンスにもを追加することをお勧めします。