Diccionario Python de los campos de un objeto.

Resuelto Julio César asked hace 16 años • 21 respuestas

¿Sabe si existe una función incorporada para crear 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.

Julio César avatar Sep 15 '08 01:09 Julio César
Aceptado

Tenga en cuenta que la mejor práctica en Python 2.7 es utilizar clases de nuevo estilo (no necesarias con Python 3), es decir

class Foo(object):
   ...

Además, existe 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ás tus métodos a nivel de clase y tus 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 varsfunción incorporada:

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

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

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

    # etc...
user6868 avatar Sep 15 '2008 13:09 user6868

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

Berislav Lopac avatar Aug 02 '2015 08:08 Berislav Lopac

El dirincorporado le brindará todos los atributos del objeto, incluidos métodos especiales como __str__y __dict__muchos 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' }

Entonces, puedes extender esto para devolver solo atributos de datos y no métodos, definiendo tu propsfunción de esta 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
dF. avatar Sep 14 '2008 18:09 dF.