Можно ли определить repr для класса, а не для экземпляра? [дубликат]
На этот вопрос уже есть ответ здесь:
Могу ли я определить __repr__
для класса, а не для экземпляра? Например, я пытаюсь сделать это
class A(object):
@classmethod
def __repr__(cls):
return 'My class %s' % cls
То, что я получаю, это
In [58]: a=A()
In [59]: a
Out[59]: My class <class '__main__.A'>
In [60]: A
Out[60]: __main__.A
Я пытаюсь сделать вывод строки 60 похожим на "мой класс А", а не на причина, по которой я хочу это сделать, заключается в том, что я создаю много классов, используя метакласс Python. И мне нужен более читаемый способ идентификации класса, чем биржевой репр.
2 ответа:
Вам нужно определить
__repr__
в метаклассе.class Meta(type): def __repr__(cls): return 'My class %s' % cls.__name__ class A(object): __metaclass__ = Meta
__repr__
возвращает представление экземпляра объекта. Таким образом, определяя__repr__
наA
, вы указываете, как вы хотитеrepr(A())
выглядеть.Чтобы определить представление класса, необходимо определить, как представлен экземпляр
type
. В этом случае заменитеtype
пользовательским метаклассом с__repr__
, определенным так, как вам нужно.>> repr(A) My class A
Если вы хотите определить пользовательский
__repr__
для каждого класса, я не буду конечно, есть особенно чистый способ сделать это. Но вы могли бы сделать что-то вроде этого.class Meta(type): def __repr__(cls): if hasattr(cls, '_class_repr'): return getattr(cls, '_class_repr')() else: return super(Meta, cls).__repr__() class A(object): __metaclass__ = Meta @classmethod def _class_repr(cls): return 'My class %s' % cls.__name__ class B(object): __metaclass__ = Meta
Затем вы можете настроить на основе каждого класса.
>> repr(A) My class A >> repr(B) <__main__.B object at 0xb772068c>
Могу ли я определить _ _ repr__ для класса, а не экземпляра?
Конечно, я продемонстрирую здесь, с
__repr__
, который проходит тестrepr
.class Type(type): def __repr__(cls): """ >>> Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None}) Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None}) """ name = cls.__name__ parents = ', '.join(b.__name__ for b in cls.__bases__) if parents: parents += ',' namespace = ', '.join(': '.join( (repr(k), repr(v) if not isinstance(v, type) else v.__name__)) for k, v in cls.__dict__.items()) return 'Type(\'{0}\', ({1}), {{{2}}})'.format(name, parents, namespace) def __eq__(cls, other): return (cls.__name__, cls.__bases__, cls.__dict__) == ( other.__name__, other.__bases__, other.__dict__)
И продемонстрировать:
class Foo(object): pass class Bar(object): pass
Либо Python 2:
class Baz(Foo, Bar): __metaclass__ = Type
Или Python 3:
class Baz(Foo, Bar, metaclass=Type): pass
Или довольно универсально:
Baz = Type('Baz', (Foo, Bar), {}) >>> Baz Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})
И выполнить тест
repr
:def main(): print Baz assert Baz == eval(repr(Baz))
Что такое
repr
тест? Это вышеприведенный тест из документации поrepr
:>>> help(repr) Help on built-in function repr in module __builtin__: repr(...) repr(object) -> string Return the canonical string representation of the object. For most object types, eval(repr(object)) == object.