recorrer todas las variables miembro de una clase en Python

91

¿Cómo se obtiene una lista de todas las variables en una clase que es iterable? Algo así como los lugareños (), pero para una clase

class Example(object):
    bool143 = True
    bool2 = True
    blah = False
    foo = True
    foobar2000 = False

    def as_list(self)
       ret = []
       for field in XXX:
           if getattr(self, field):
               ret.append(field)
       return ",".join(ret)

esto debería volver

>>> e = Example()
>>> e.as_list()
bool143, bool2, foo
sacerdotec
fuente
¿Por qué no puedo usar for field in [ self.bool143, self.bool2, self.blah, self.foo, self.foobar2000 ]? ¿Cómo sucede que no conoce las variables de instancia de la clase?
S.Lott
4
S.Lott: eso es lo que terminé haciendo de todos modos. En mi código real, tengo como 40 variables, y pensé que sería mejor y más SECO no tener que hacer manualmente la lista de iteraciones.
sacerdotec
3
Posible duplicado de Iterar sobre atributos de objeto en Python
Trevor Boyd Smith

Respuestas:

151
dir(obj)

le da todos los atributos del objeto. Debe filtrar los miembros de los métodos, etc. usted mismo:

class Example(object):
    bool143 = True
    bool2 = True
    blah = False
    foo = True
    foobar2000 = False

example = Example()
members = [attr for attr in dir(example) if not callable(getattr(example, attr)) and not attr.startswith("__")]
print members   

Te regalaré:

['blah', 'bool143', 'bool2', 'foo', 'foobar2000']
truppo
fuente
9
por qué instanciar un objeto: dir (Ejemplo ()) en lugar de solo el tipo de clase dir (Ejemplo)
Erdal
8
y ¿cómo se obtienen los valores?
Knutole
7
@knutole: getattr (objeto, attr)
opello
8
¿Cómo callable(attr)funciona? ¿No es attruna cuerda?
cubuspl42
6
debería haber usado vars(Example).items()o en vars(instance.__class__).items()lugar de dir()si desea verificar si se puede llamar o no porque dir solo devolverá ' strings como nombres ..
rrw
117

Si solo desea las variables (sin funciones) use:

vars(your_object)
Nimo
fuente
5
Todavía es necesario para filtrar vars pero esta es la respuesta correcta
gaborous
3
Me gusta mucho este enfoque, lo usaré para averiguar qué serializar antes de enviar estados a través de la red, por ejemplo ...
Thom
7
varsno no incluir las variables de clase, sólo las variables de instancia.
DilithiumMatrix
2
@DilithiumMatrix necesita usar vars (THECLASSITSELF) en la clase misma para obtener variables de clase. Comprueba mi respuesta a continuación.
AmirHossein
2
Usando este método para responder específicamente a la pregunta del OP: members = list(vars(example).keys())as (al menos en python3) varsdevuelve una dictasignación del nombre de la variable miembro a su valor.
Michael Hall
28

@truppo: su respuesta es casi correcta, pero invocable siempre devolverá falso ya que solo está pasando una cadena. Necesita algo como lo siguiente:

[attr for attr in dir(obj()) if not callable(getattr(obj(),attr)) and not attr.startswith("__")]

que filtrará las funciones

usuario235925
fuente
6
>>> a = Example()
>>> dir(a)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__',
'__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__sizeof__', '__str__', '__subclasshook__', 'bool143', 'bool2', 'blah',
'foo', 'foobar2000', 'as_list']

—Como ve, eso le da todos los atributos, así que tendrá que filtrar un poco. Pero básicamente, dir()es lo que estás buscando.

balpha
fuente
-1
row2dict = lambda r: {c.name: str(getattr(r, c.name)) for c in r.__table__.columns} if r else {}

Utilizar esta.

usuario1825586
fuente
Engañoso. No hay ' tabla ' de atributos en las clases de forma predeterminada.
ben26941
-2
    class Employee:
    '''
    This class creates class employee with three attributes 
    and one function or method
    '''

    def __init__(self, first, last, salary):
        self.first = first
        self.last = last
        self.salary = salary

    def fullname(self):
        fullname=self.first + ' ' + self.last
        return fullname

emp1 = Employee('Abhijeet', 'Pandey', 20000)
emp2 = Employee('John', 'Smith', 50000)

print('To get attributes of an instance', set(dir(emp1))-set(dir(Employee))) # you can now loop over
Abhijeet Pandey
fuente
-3

La forma más sencilla de hacerlo es guardar todas las instancias de la clase en un archivo list.

a = Example()
b = Example()
all_examples = [ a, b ]

Los objetos no surgen espontáneamente. Alguna parte de su programa los creó por una razón. La creación se hace por una razón. Recopilarlos en una lista también se puede hacer por una razón.

Si usa una fábrica, puede hacer esto.

class ExampleFactory( object ):
    def __init__( self ):
        self.all_examples= []
    def __call__( self, *args, **kw ):
        e = Example( *args, **kw )
        self.all_examples.append( e )
        return e
    def all( self ):
        return all_examples

makeExample= ExampleFactory()
a = makeExample()
b = makeExample()
for i in makeExample.all():
    print i
S. Lot
fuente
Me gusta la idea (podría usarla en un proyecto actual). Sin embargo, no es una respuesta a la pregunta: el OP quiere enumerar los atributos, no las instancias en sí.
Balpha
@balpha: Vaya. No leí la pregunta. El 90% de las veces, es un duplicado de "cómo encuentro todas las instancias de una clase". La pregunta real (ahora que la señala) no es sensata. Conoces las variables de instancia, solo haz una lista.
S.Lott