pętla po wszystkich zmiennych składowych klasy w Pythonie


91

Jak uzyskać listę wszystkich zmiennych w klasie, którą można iterować? Trochę jak locals (), ale dla klasy

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)

to powinno powrócić

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

Dlaczego nie można używać for field in [ self.bool143, self.bool2, self.blah, self.foo, self.foobar2000 ]? Jak to się dzieje, że nie znasz zmiennych instancji klasy?
S.Lott,

4
S.Lott: i tak właśnie to zrobiłem. W moim prawdziwym kodzie mam około 40 zmiennych i pomyślałem, że byłoby lepiej i bardziej SUCHA nie musieć ręcznie tworzyć listy iteracji.
ksiądz

Odpowiedzi:


151
dir(obj)

daje wszystkie atrybuty obiektu. Musisz samodzielnie odfiltrować członków z metod itp:

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   

Da tobie:

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

9
po co tworzyć instancję obiektu: dir (Example ()) zamiast tylko klasy typu dir (Przykład)
Erdal

8
i jak otrzymujesz wartości?
knutole

7
@knutole: getattr (obiekt,
atr

8
Jak to callable(attr)działa? Czy to nie attrjest ciąg?
cubuspl42

6
powinieneś użyć vars(Example).items()lub vars(instance.__class__).items()zamiast tego, dir()czy chcesz sprawdzić, czy jest wywoływalny, czy nie, ponieważ dir zwróci tylko stringjako nazwy ..
rrw

117

Jeśli chcesz tylko zmienne (bez funkcji) użyj:

vars(your_object)

5
Nadal musisz filtrować vars, ale to jest poprawna odpowiedź
gaborous

3
naprawdę podoba mi się to podejście, wykorzystam je, aby dowiedzieć się, co serializować przed wysłaniem stanów na przykład przez sieć ...
Thom

7
varsma nie zawierać zmienne klasy, tylko zmienne instancji.
DilithiumMatrix

2
@DilithiumMatrix musisz użyć zmiennej vars (THECLASSITSELF) na samej klasie, aby uzyskać zmienne klasy. Sprawdź moją odpowiedź poniżej.
AmirHossein

2
Użycie tej metody, aby konkretnie odpowiedzieć na pytanie OP: members = list(vars(example).keys())as (przynajmniej w python3) varszwraca dictodwzorowanie nazwy zmiennej składowej na jej wartość.
Michael Hall

28

@truppo: twoja odpowiedź jest prawie poprawna, ale callable zawsze zwróci false, ponieważ przekazujesz tylko ciąg. Potrzebujesz czegoś takiego:

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

które odfiltrują funkcje


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

- jak widzisz, daje to wszystkie atrybuty, więc będziesz musiał trochę odfiltrować. Ale w zasadzie dir()to jest to, czego szukasz.


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

Użyj tego.


Zwodniczy. W klasach domyślnie nie ma atrybutu „ table ”.
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

Prostym sposobem na to jest zapisanie wszystkich instancji klasy w pliku list.

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

Przedmioty nie powstają spontanicznie. Jakaś część twojego programu stworzyła je z jakiegoś powodu. Stworzenie nie bez powodu. Zbieranie ich na liście może mieć również powód.

Jeśli korzystasz z fabryki, możesz to zrobić.

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

Podoba mi się ten pomysł (mogę go wykorzystać w obecnym projekcie). Nie jest to jednak odpowiedź na pytanie: OP chce wymienić atrybuty, a nie same instancje.
balpha

@balpha: Ups. Nie przeczytałem pytania. W 90% przypadków jest to duplikat „jak znaleźć wszystkie wystąpienia klasy”. Właściwe pytanie (teraz, kiedy to wskazałeś) nie jest rozsądne. Znasz zmienne instancji, po prostu zrób listę.
S.Lott
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.