ciclo su tutte le variabili membro di una classe in python


91

Come si ottiene un elenco di tutte le variabili in una classe iterabile? Un po 'come gente del posto (), ma per una 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)

questo dovrebbe tornare

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

Perché non puoi usare l'uso for field in [ self.bool143, self.bool2, self.blah, self.foo, self.foobar2000 ]? Come mai non conosci le variabili di istanza della classe?
S.Lott

4
S.Lott: questo è quello che ho finito per fare comunque. Nel mio codice reale, ho circa 40 variabili e ho pensato che sarebbe stato meglio e più DRY non dover creare manualmente l'elenco delle iterazioni.
priestc

Risposte:


151
dir(obj)

ti dà tutti gli attributi dell'oggetto. Devi filtrare i membri dai metodi ecc. Tu stesso:

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   

Ti darà:

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

9
perché istanziare un oggetto: dir (Example ()) invece del solo tipo di classe dir (Esempio)
Erdal

8
e come si ottengono i valori?
knutole

7
@knutole: getattr (object, attr)
opello

8
Come callable(attr)funziona? Non è attruna stringa?
cubuspl42

6
avresti dovuto usare vars(Example).items()o vars(instance.__class__).items()invece di dir()se vuoi controllare se è richiamabile o meno perché dir restituirà solo stringi nomi come ..
rrw

117

Se vuoi solo le variabili (senza funzioni) usa:

vars(your_object)

5
Hai ancora bisogno di filtrare le variabili, ma questa è la risposta corretta
gaborous

3
mi piace molto questo approccio, lo userò per scoprire cosa serializzare prima di inviare stati sulla rete, ad esempio ...
Thom

7
varsnon non includere le variabili di classe, solo le variabili di istanza.
DilithiumMatrix

2
@DilithiumMatrix è necessario utilizzare vars (THECLASSITSELF) sulla classe stessa per ottenere le variabili di classe. Controlla la mia risposta qui sotto.
AmirHossein

2
Utilizzando questo metodo per rispondere in modo specifico alla domanda dell'OP: members = list(vars(example).keys())as (almeno in python3) varsrestituisce una dictmappatura del nome della variabile membro al suo valore.
Michael Hall

28

@truppo: la tua risposta è quasi corretta, ma callable restituirà sempre false dato che stai solo passando una stringa. Hai bisogno di qualcosa come il seguente:

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

che filtrerà le funzioni


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

- come vedi, questo ti dà tutti gli attributi, quindi dovrai filtrare un po '. Ma in fondo, dir()è quello che stai cercando.


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

Usa questo.


Ingannevole. Per impostazione predefinita , non esiste alcun attributo " tabella " nelle classi.
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

Il modo più semplice per farlo è salvare tutte le istanze della classe in un file list.

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

Gli oggetti non nascono spontaneamente. Qualche parte del tuo programma li ha creati per un motivo. La creazione è fatta per un motivo. Anche la raccolta in un elenco può essere eseguita per un motivo.

Se usi una fabbrica, puoi farlo.

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

Mi piace l'idea (potrei effettivamente usarla in un progetto in corso). Non è una risposta alla domanda, però: l'OP vuole elencare gli attributi, non le istanze stesse.
balpha

@balpha: Ooops. Non ho letto la domanda. Il 90% delle volte è un duplicato di "come trovo tutte le istanze di una classe". La vera domanda (ora che me lo fai notare) non è sensata. Conosci le variabili di istanza, crea solo un elenco.
S.Lott
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.