boucle sur toutes les variables membres d'une classe en python


91

Comment obtenir une liste de toutes les variables d'une classe itérative? Un peu comme les locaux (), mais pour une classe

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)

cela devrait revenir

>>> e = Example()
>>> e.as_list()
bool143, bool2, foo

Pourquoi ne peut pas utiliser l'utilisation for field in [ self.bool143, self.bool2, self.blah, self.foo, self.foobar2000 ]? Comment se fait-il que vous ne connaissiez pas les variables d'instance de la classe?
S.Lott

4
S.Lott: c'est ce que j'ai fini par faire de toute façon. Dans mon vrai code, j'ai environ 40 variables, et j'ai pensé que ce serait mieux et plus DRY de ne pas avoir à faire manuellement la liste des itérations.
Priestc

Réponses:


151
dir(obj)

vous donne tous les attributs de l'objet. Vous devez filtrer vous-même les membres des méthodes, etc.:

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 donnera:

['blah', 'bool143', 'bool2', 'foo', 'foobar2000']

9
pourquoi instancier un objet: dir (Exemple ()) au lieu du seul type de classe dir (Exemple)
Erdal

8
et comment obtenez-vous les valeurs?
knutole

7
@knutole: getattr (objet, attr)
opello

8
Comment ça callable(attr)marche? N'est-ce pas attrune chaîne?
cubuspl42

6
vous devriez avoir utilisé vars(Example).items()ou au vars(instance.__class__).items()lieu de dir()si vous voulez vérifier si son appelable ou non parce que dir ne renverra ' strings comme noms ..
RRW

117

Si vous ne voulez que les variables (sans fonctions), utilisez:

vars(your_object)

5
Vous devez toujours filtrer les variables, mais c'est la bonne réponse
gaborous

3
vraiment comme cette approche va l'utiliser pour savoir ce qu'il faut sérialiser avant d'envoyer des états sur le réseau par exemple ...
Thom

7
varsn'inclut pas les variables de classe, uniquement les variables d'instance.
DilithiumMatrix

2
@DilithiumMatrix vous devez utiliser vars (THECLASSITSELF) sur la classe elle-même pour obtenir des variables de classe. Vérifiez ma réponse ci-dessous.
AmirHossein

2
Utiliser cette méthode pour répondre spécifiquement à la question de l'OP: members = list(vars(example).keys())as (au moins en python3) varsrenvoie un dictmappage du nom de la variable membre à sa valeur.
Michael Hall

28

@truppo: votre réponse est presque correcte, mais callable retournera toujours false puisque vous ne faites que passer une chaîne. Vous avez besoin de quelque chose comme ce qui suit:

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

qui filtrera les fonctions


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

- comme vous le voyez, cela vous donne tous les attributs, vous devrez donc filtrer un peu. Mais en gros, dir()c'est ce que vous recherchez.


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

Utilisez ceci.


Trompeur. Il n'y a pas d'attribut « table » dans les classes par défaut.
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

Le moyen le plus simple de procéder consiste à enregistrer toutes les instances de la classe dans un fichier list.

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

Les objets ne naissent pas spontanément. Une partie de votre programme les a créés pour une raison. La création est faite pour une raison. Les rassembler dans une liste peut également être fait pour une raison.

Si vous utilisez une usine, vous pouvez le faire.

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

J'aime l'idée (je pourrais l'utiliser dans un projet en cours). Ce n'est cependant pas une réponse à la question: l'OP veut lister les attributs, pas les instances elles-mêmes.
balpha le

@balpha: Oups. Je n'ai pas lu la question. 90% du temps, c'est un doublon de «comment trouver toutes les instances d'une classe». La question réelle (maintenant que vous le faites remarquer) n'est pas raisonnable. Vous connaissez les variables d'instance, faites simplement une liste.
S.Lott
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.