Рассмотрим этот класс:
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, то шесть модулей помогут вам:
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, вышеописанный подход на основе классов работает отлично. Но если у вас их несколько, вам нужно сгенерировать метакласс, аналогичный MC
каждому, и это может стать утомительным. В этом случае продвижение метапрограммирования на шаг вперед и создание фабрики метаклассов делает вещи немного чище:
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)
стандартный вывод:
Wahaha!
Недостатки:
C
без суперкласса (нет class C:
)C
экземпляры будут экземплярами некоторого странного происхождения, так что, вероятно, будет хорошей идеей добавить и __repr__
для экземпляров.