Могу ли я определить __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 похожим на "Мой класс A", а не для экземпляра a. Я хочу сделать это потому, что я генерирую множество классов, используя метакласс 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.