зациклювання всіх змінних-членів класу в 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.