зациклювання всіх змінних-членів класу в python


91

Як отримати список усіх змінних у класі, який можна повторити? Начебто місцеві жителі (), але для класу

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)

це повинно повернутися

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

Чому не можна використовувати use for field in [ self.bool143, self.bool2, self.blah, self.foo, self.foobar2000 ]? Як трапляється так, що ви не знаєте змінних екземпляра класу?
S.Lott,

4
С.Лотт: ось що я все одно закінчив робити. У моєму реальному коді у мене є близько 40 змінних, і я вважав, що було б краще і більш СУХО, щоб не потрібно вручну робити список ітерацій.
священик

Відповіді:


151
dir(obj)

надає всі атрибути об’єкта. Вам потрібно самостійно відфільтрувати членів з методів тощо:

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   

Дасть вам:

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

9
навіщо створювати екземпляр об’єкта: dir (Приклад ()) замість просто dir типу класу (Приклад)
Ердал

8
і як ви отримуєте значення?
knutole

7
@knutole: getattr (object, attr)
opello

8
Як callable(attr)працює? Хіба це не attrструна?
cubuspl42

6
вам слід було скористатися vars(Example).items()чи vars(instance.__class__).items()замість цього, dir()якщо ви хочете перевірити, чи можна його викликати чи ні, тому що dir буде повертати лише stringімена як імена ..
rrw

117

Якщо ви хочете лише змінні (без функцій), використовуйте:

vars(your_object)

5
Вам все-таки потрібно відфільтрувати вари, але це правильна відповідь
важкий

3
дуже подобається такий підхід, який використовуватиме його, щоб дізнатись, що серіалізувати перед тим, як відправляти штати через мережу, наприклад ...
Том,

7
varsце НЕ включає в себе змінні класу, тільки змінні екземпляра.
DilithiumMatrix

2
@DilithiumMatrix вам потрібно використовувати vars (THECLASSITSELF) у самому класі, щоб отримати змінні класу. Перевірте мою відповідь нижче.
AmirHossein

2
Використовуючи цей метод, щоб конкретно відповісти на запитання OP: members = list(vars(example).keys())as (принаймні в python3) varsповертає dictвідображення імені змінної-члена до її значення.
Майкл Холл,

28

@truppo: ваша відповідь майже правильна, але виклик завжди повертає false, оскільки ви просто передаєте рядок. Вам потрібно щось на зразок наступного:

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

який відфільтрує функції


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

—Як бачите, це дає вам усі атрибути, тому вам доведеться трохи відфільтрувати. Але в основному dir()це те, що ви шукаєте.


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

Використовуй це.


Оманливий. У класах за замовчуванням немає атрибута ' таблиця '.
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

Найпростіший спосіб зробити це - зберегти всі екземпляри класу в list.

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

Предмети не виникають спонтанно. Якась частина вашої програми створила їх неспроста. Створення зроблено неспроста. Збір їх у списку також може бути здійснений з причини.

Якщо ви використовуєте завод, ви можете це зробити.

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

Мені подобається ідея (я міг би насправді використовувати це в поточному проекті). Однак це не відповідь на запитання: ОП хоче перерахувати атрибути, а не самі екземпляри.
balpha

@balpha: На жаль. Не прочитав запитання. У 90% випадків це дублікат "як знайти всі екземпляри класу". Фактичне питання (тепер, коли ви на це вказуєте) не є розумним. Ви знаєте змінні екземпляра, просто складіть список.
S.Lott,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.