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

¿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

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']

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)

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


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.


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

Utilizar esta.


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

-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

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.