Как определить метод __str__ для класса?

В Python класс object служит в качестве суперкласса корня для всех классов (нового стиля). По умолчанию, по крайней мере, применение str и repr к экземпляру класса любого подкласса object приводит к такому же результату:

>>> class spam(object): pass
... 
>>> str(spam)
"<class '__main__.spam'>"
>>> str(spam) == repr(spam)

Я хотел бы определить подкласс object, скажем fancyobject, который во всех отношениях идентичен object, за исключением того, что применение str и repr to fancyobject само создает разные выходы:

>>> class ham(fancyobject): pass
...
>>> str(ham)
'ham'
>>> repr(ham)
"<class '__main__.ham'>"

Есть ли способ сделать это в Python?

PS: Я знаю специальный метод __str__, но я понимаю, что если класс A переопределяет __str__, тогда метод переопределения вызывается только тогда, когда str вызывается в экземплярах A, а не когда он вызывается непосредственно на A. То есть:.

>>> class A(object):
...     def __str__(self):
...         return 'from new __str__: ' + object.__str__(self)
... 
>>> str(A())
'from new __str__: <__main__.A object at 0x7f79c62a5310>'
>>> str(A)
"<class '__main__.A'>"

Ответ 1

Фактически для типов применяется тот же механизм, что и для экземпляров объектов. Типы - это просто объекты, поэтому они преобразуются в строки, вызывая метод __str__() для своего типа, который называется "метаклассом". Поэтому вам нужно перезаписать метод __str__() в метаклассе:

class fancytype(type):
    def __str__(self):
        return self.__name__
class ham(object):
    __metaclass__ = fancytype
print ham

печатает

ham

Ответ 2

Вы также можете установить метаклас по умолчанию для всего модуля, например

class fancytype(type):
    def __str__(self):
        return self.__name__

__metaclass__ = fancytype

class ham:
    pass
print ham