Método __repr__ automático

Quiero tener una representación simple de cualquier clase, como { property = value } , ¿hay auto __repr__ ?

Sí, puedes hacer una clase “AutoRepr” y dejar que todas las demás clases la amplíen:

 >>> class AutoRepr(object): ... def __repr__(self): ... items = ("%s = %r" % (k, v) for k, v in self.__dict__.items()) ... return "<%s: {%s}>" % (self.__class__.__name__, ', '.join(items)) ... >>> class AnyOtherClass(AutoRepr): ... def __init__(self): ... self.foo = 'foo' ... self.bar = 'bar' ... >>> repr(AnyOtherClass()) "" 

Tenga en cuenta que el código anterior no actuará bien en las estructuras de datos que se refieran (directa o indirectamente). Como alternativa, puede definir una función que funcione en cualquier tipo:

 >>> def autoRepr(obj): ... try: ... items = ("%s = %r" % (k, v) for k, v in obj.__dict__.items()) ... return "<%s: {%s}." % (obj.__class__.__name__, ', '.join(items)) ... except AttributeError: ... return repr(obj) ... >>> class AnyOtherClass(object): ... def __init__(self): ... self.foo = 'foo' ... self.bar = 'bar' ... >>> autoRepr(AnyOtherClass()) "" >>> autoRepr(7) '7' >>> autoRepr(None) 'None' 

Tenga en cuenta que la función anterior no está definida recursivamente, a propósito, por la razón mencionada anteriormente.

Manera más simple:

 def __repr__(self): return str(self.__dict__) 

Quieres decir

 __dict__ 

?

Bueno, jugué un poco con otras respuestas y obtuve una solución muy bonita:

 class data: @staticmethod def repr(obj): items = [] for prop, value in obj.__dict__.items(): try: item = "%s = %r" % (prop, value) assert len(item) < 20 except: item = "%s: <%s>" % (prop, value.__class__.__name__) items.append(item) return "%s(%s)" % (obj.__class__.__name__, ', '.join(items)) def __init__(self, cls): cls.__repr__ = data.repr self.cls = cls def __call__(self, *args, **kwargs): return self.cls(*args, **kwargs) 

Lo usas como decorador:

 @data class PythonBean: def __init__(self): self.int = 1 self.list = [5, 6, 7] self.str = "hello" self.obj = SomeOtherClass() 

y saca una __repr__ inteligente de la caja:

 PythonBean(int = 1, obj: , list = [5, 6, 7], str = 'hello') 

Esto funciona con cualquier clase recursiva, incluyendo estructuras de árbol. Si intenta poner una auto-referencia en la clase self.ref = self , la función intentará (con éxito) resolverla durante aproximadamente un segundo.

Por supuesto, siempre tenga en cuenta a su jefe; al mío no le gustaría tal syntax ())

Utilizo esta función auxiliar para generar repr s para mis clases. Es fácil de ejecutar en una función de prueba de unidad, es decir.

 def test_makeRepr(self): makeRepr(Foo, Foo(), "anOptional space delimitedString ToProvideCustom Fields") 

esto debería generar una cantidad de repeticiones potenciales en la consola, que luego puede copiar / pegar en su clase.

 def makeRepr(classObj, instance = None, customFields = None): """Code writing helper function that will generate a __repr__ function that can be copy/pasted into a class definition. Args: classObj (class): instance (class): customFields (string): Returns: None: Always call the __repr__ function afterwards to ensure expected output. ie. print(foo) def __repr__(self): msg = "" attributes = [self.var1, self.var2] return msg.format(*attributes) """ if isinstance(instance, classObj): className = instance.__class__.__name__ else: className=classObj.__name__ print('Generating a __repr__ function for: ', className,"\n") print("\tClass Type: "+classObj.__name__, "has the following fields:") print("\t"+" ".join(classObj.__dict__.keys()),"\n") if instance: print("\tInstance of: "+instance.__class__.__name__, "has the following fields:") print("\t"+" ".join(instance.__dict__.keys()),"\n") else: print('\tInstance of: Instance not provided.\n') if customFields: print("\t"+"These fields were provided to makeRepr:") print("\t"+customFields,"\n") else: print("\t"+"These fields were provided to makeRepr: None\n") print("Edit the list of fields, and rerun makeRepr with the new list if necessary.\n\n") print("repr with class type:\n") classResult = buildRepr( classObj.__name__, " ".join(classObj.__dict__.keys())) print(classResult,"\n\n") if isinstance(instance, classObj): instanceResult = buildRepr( instance.__class__.__name__, " ".join(instance.__dict__.keys())) else: instanceResult = "\t-----Instance not provided." print("repr with instance of class:\n") print(instanceResult,"\n\n") if customFields: customResult = buildRepr( classObj.__name__, customFields) else: customResult = '\t-----Custom fields not provided' print("repr with custom fields and class name:\n") print(customResult,"\n\n") print('Current __repr__') print("Class Object: ",classObj) if instance: print("Instance: ",instance.__repr__()) else: print("Instance: ", "None") def buildRepr(typeName,fields): funcDefLine = "def __repr__(self):" msgLineBase = ' msg = "<{typename}({attribute})>"' attributeListLineBase = ' attributes = [{attributeList}]' returnLine = ' return msg.format(*attributes)' x = ['self.' + x for x in fields.split()] xResult = ", ".join(x) y = [x + ' = {}' for x in fields.split()] yResult = ', '.join(y) msgLine = msgLineBase.format(typename = typeName, attribute = yResult) attributeListLine = attributeListLineBase.format(attributeList = xResult) result = "{declaration}\n{message}\n{attributes}\n{returnLine}".format(declaration = funcDefLine, message = msgLine, attributes = attributeListLine, returnLine =returnLine ) return result