2012-01-21 10 views
11

Posso definire un __repr__ per una classe piuttosto che un'istanza? Per esempio, io sto cercando di fare questoPosso definire un __repr__ per una classe piuttosto che un'istanza?

class A(object): 
    @classmethod 
    def __repr__(cls): 
     return 'My class %s' % cls 

Quello che ottengo è

In [58]: a=A() 

In [59]: a 
Out[59]: My class <class '__main__.A'> 

In [60]: A 
Out[60]: __main__.A 

sto cercando di ottenere l'uscita della linea 60 a guardare come "La mia Classe A", non per l'istanza a. La ragione per cui voglio farlo è che sto generando un sacco di classi usando il metaclass di Python. E voglio un modo più leggibile per identificare la classe rispetto alla replica di azioni.

+0

Ha frainteso il tuo problema. Ha pubblicato un'altra risposta (si spera corretta). –

risposta

18

È necessario definire __repr__ sul metaclass.

class Meta(type): 
    def __repr__(cls): 
     return 'My class %s' % cls.__name__ 

class A(object): 
    __metaclass__ = Meta 

__repr__ restituisce una rappresentazione di un'istanza di un oggetto. Quindi, definendo __repr__ su A, stai specificando ciò che vuoi che sia repr(A()).

Per definire la rappresentazione della classe, è necessario definire la modalità di rappresentazione di un'istanza di type. In questo caso, sostituire type con una metaclasse personalizzata con __repr__ definita come necessario.

>> repr(A) 
My class A 

Se si desidera definire un costume __repr__ per ogni classe, io non sono sicuro che c'è un modo particolarmente pulito per farlo. Ma potresti fare qualcosa di simile.

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 

Quindi è possibile personalizzare in base alla classe.

>> repr(A) 
My class A 
>> repr(B) 
<__main__.B object at 0xb772068c> 
+0

Mi picchia, +1. –

+3

Si noti che in Python 3 '__metaclass__' non ha significato speciale, invece si dovrebbe usare' classe A (metaclass = Meta) '. –

+0

@RobWouters Grazie :) Non sapevo che era cambiato. –

0

posso definire un __repr__ per una classe piuttosto che un esempio?

Certo, lo dimostrano qui, con una __repr__ che supera il test 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__) 

E per dimostrare:

class Foo(object): pass 

class Bar(object): pass 

In entrambi Python 2:

class Baz(Foo, Bar): 
    __metaclass__ = Type 

o Python 3:

class Baz(Foo, Bar, metaclass=Type): 
    pass 

o abbastanza universalmente:

Baz = Type('Baz', (Foo, Bar), {}) 
>>> Baz 
Type('Baz', (Foo, Bar,), {'__module__': '__main__', '__doc__': None}) 

E per fare il test repr:

def main(): 
    print Baz 
    assert Baz == eval(repr(Baz)) 

Qual è il test repr?È il test sopra riportato dalla documentazione su 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. 
Problemi correlati