resueltos recorrer lista elementos ejercicios diccionarios diccionario dentro convertir agregar python dictionary attributes object metaprogramming

recorrer - Diccionario de Python de los campos de un objeto



lista de diccionarios python (10)

¿Sabe si hay una función incorporada para construir un diccionario a partir de un objeto arbitrario? Me gustaría hacer algo como esto:

>>> class Foo: ... bar = ''hello'' ... baz = ''world'' ... >>> f = Foo() >>> props(f) { ''bar'' : ''hello'', ''baz'' : ''world'' }

NOTA: No debe incluir métodos. Sólo campos.


Para construir un diccionario a partir de un objeto arbitrario, es suficiente usar __dict__ .

Esto pierde los atributos que el objeto hereda de su clase. Por ejemplo,

class c(object): x = 3 a = c()

hasattr (a, ''x'') es verdadero, pero ''x'' no aparece en un .__ dict__


PYTHON 3:

class DateTimeDecoder(json.JSONDecoder): def __init__(self, *args, **kargs): JSONDecoder.__init__(self, object_hook=self.dict_to_object, *args, **kargs) def dict_to_object(self, d): if ''__type__'' not in d: return d type = d.pop(''__type__'') try: dateobj = datetime(**d) return dateobj except: d[''__type__''] = type return d def json_default_format(value): try: if isinstance(value, datetime): return { ''__type__'': ''datetime'', ''year'': value.year, ''month'': value.month, ''day'': value.day, ''hour'': value.hour, ''minute'': value.minute, ''second'': value.second, ''microsecond'': value.microsecond, } if isinstance(value, decimal.Decimal): return float(value) if isinstance(value, Enum): return value.name else: return vars(value) except Exception as e: raise ValueError

Ahora puedes usar el código anterior dentro de tu propia clase:

class Foo(): def toJSON(self): return json.loads( json.dumps(self, sort_keys=True, indent=4, separators=('','', '': ''), default=json_default_format), cls=DateTimeDecoder) Foo().toJSON()


Creo que la forma más fácil es crear un atributo getitem para la clase. Si necesita escribir en el objeto, puede crear un setattr personalizado. Aquí hay un ejemplo para getitem :

class A(object): def __init__(self): self.b = 1 self.c = 2 def __getitem__(self, item): return self.__dict__[item] # Usage: a = A() a.__getitem__(''b'') # Outputs 1 a.__dict__ # Outputs {''c'': 2, ''b'': 1} vars(a) # Outputs {''c'': 2, ''b'': 1}

dict genera los atributos de los objetos en un diccionario y el objeto del diccionario se puede utilizar para obtener el elemento que necesita.


El dir incorporado le proporcionará todos los atributos del objeto, incluidos métodos especiales como __str__ , __dict__ y __dict__ otros que probablemente no desee. Pero puedes hacer algo como:

>>> class Foo(object): ... bar = ''hello'' ... baz = ''world'' ... >>> f = Foo() >>> [name for name in dir(f) if not name.startswith(''__'')] [ ''bar'', ''baz'' ] >>> dict((name, getattr(f, name)) for name in dir(f) if not name.startswith(''__'')) { ''bar'': ''hello'', ''baz'': ''world'' }

Así que puede extender esto para que solo devuelva atributos de datos y no métodos, definiendo su función de props siguiente manera:

import inspect def props(obj): pr = {} for name in dir(obj): value = getattr(obj, name) if not name.startswith(''__'') and not inspect.ismethod(value): pr[name] = value return pr


En lugar de x.__dict__ , en realidad es más pythónico usar vars(x) .


Me he conformado con una combinación de ambas respuestas:

dict((key, value) for key, value in f.__dict__.iteritems() if not callable(value) and not key.startswith(''__''))


Pensé que me tomaría un tiempo mostrarte cómo puedes traducir un objeto a dict a través de dict(obj) .

class A(object): d = ''4'' e = ''5'' f = ''6'' def __init__(self): self.a = ''1'' self.b = ''2'' self.c = ''3'' def __iter__(self): # first start by grabbing the Class items iters = dict((x,y) for x,y in A.__dict__.items() if x[:2] != ''__'') # then update the class items with the instance items iters.update(self.__dict__) # now ''yield'' through the items for x,y in iters.items(): yield x,y a = A() print(dict(a)) # prints "{''a'': ''1'', ''c'': ''3'', ''b'': ''2'', ''e'': ''5'', ''d'': ''4'', ''f'': ''6''}"

La sección clave de este código es la función __iter__ .

Como explican los comentarios, lo primero que hacemos es agarrar los elementos de la Clase y evitar todo lo que comience con ''__''.

Una vez que haya creado ese dict , entonces puede usar la función de __dict__ update y pasar la instancia __dict__ .

Estos te darán un completo diccionario de clase + instancia de miembros. Ahora todo lo que queda es iterar sobre ellos y producir los rendimientos.

Además, si planeas usar esto mucho, puedes crear un decorador de clase @iterable .

def iterable(cls): def iterfn(self): iters = dict((x,y) for x,y in cls.__dict__.items() if x[:2] != ''__'') iters.update(self.__dict__) for x,y in iters.items(): yield x,y cls.__iter__ = iterfn return cls @iterable class B(object): d = ''d'' e = ''e'' f = ''f'' def __init__(self): self.a = ''a'' self.b = ''b'' self.c = ''c'' b = B() print(dict(b))


Respuesta tardía, pero siempre completa y en beneficio de los usuarios de Google:

def props(x): return dict((key, getattr(x, key)) for key in dir(x) if key not in dir(x.__class__))

Esto no mostrará los métodos definidos en la clase, pero seguirá mostrando campos que incluyen aquellos asignados a las lambdas o aquellos que comienzan con un subrayado doble.


Si desea enumerar parte de sus atributos, __dict__ :

def __dict__(self): d = { ''attr_1'' : self.attr_1, ... } return d # Call __dict__ d = instance.__dict__()

Esto ayuda mucho si su instance obtiene algunos datos de bloque grandes y desea empujar d a Redis como la cola de mensajes.


Tenga en cuenta que la mejor práctica en Python 2.7 es usar clases de new-style (no necesarias con Python 3), es decir

class Foo(object): ...

Además, hay una diferencia entre un ''objeto'' y una ''clase''. Para construir un diccionario a partir de un objeto arbitrario, es suficiente usar __dict__ . Por lo general, declarará sus métodos a nivel de clase y sus atributos a nivel de instancia, por lo que __dict__ debería estar bien. Por ejemplo:

>>> class A(object): ... def __init__(self): ... self.b = 1 ... self.c = 2 ... def do_nothing(self): ... pass ... >>> a = A() >>> a.__dict__ {''c'': 2, ''b'': 1}

Un mejor enfoque (sugerido por robert en los comentarios) es la función vars integrada:

>>> vars(a) {''c'': 2, ''b'': 1}

Alternativamente, dependiendo de lo que quiera hacer, podría ser bueno heredar de dict . Entonces su clase ya es un diccionario, y si lo desea, puede anular getattr y / o setattr para llamar y configurar el dict. Por ejemplo:

class Foo(dict): def __init__(self): pass def __getattr__(self, attr): return self[attr] # etc...