问题
Can I define a __repr__
for a class rather than an instance? For example, I'm trying to do this
class A(object):
@classmethod
def __repr__(cls):
return 'My class %s' % cls
What I get is
In [58]: a=A()
In [59]: a
Out[59]: My class <class '__main__.A'>
In [60]: A
Out[60]: __main__.A
I'm trying to get the output of line 60 to look like "My Class A", not for the instance a. The reason I want to do this is I'm generating a lot of classes using Python's metaclass. And I want a more readable way to identify the class than the stock repr.
回答1:
You need to define __repr__
on the metaclass.
class Meta(type):
def __repr__(cls):
return 'My class %s' % cls.__name__
class A(object):
__metaclass__ = Meta
__repr__
returns a representation of an instance of an object. So by defining __repr__
on A
, you're specifying what you want repr(A())
to look like.
To define the representation of the class, you need to define how an instance of type
is represented. In this case, replace type
with a custom metaclass with __repr__
defined as you need.
>> repr(A)
My class A
If you want to define a custom __repr__
for each class, I'm not sure there's a particularly clean way to do it. But you could do something like this.
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
Then you can customize on a per-class basis.
>> repr(A)
My class A
>> repr(B)
<__main__.B object at 0xb772068c>
回答2:
Can I define a __repr__ for a class rather than an instance?
Sure, I demonstrate here, with a __repr__
that passes the repr
test.
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__)
And to demonstrate:
class Foo(object): pass
class Bar(object): pass
Either Python 2:
class Baz(Foo, Bar):
__metaclass__ = Type
Or Python 3:
class Baz(Foo, Bar, metaclass=Type):
pass
Or fairly universally:
Baz = Type('Baz', (Foo, Bar), {})
>>> Baz
Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None})
And to do the repr
test:
def main():
print Baz
assert Baz == eval(repr(Baz))
What is the repr
test? It's the above test from the documentation on 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.
来源:https://stackoverflow.com/questions/8955754/can-i-define-a-repr-for-a-class-rather-than-an-instance