Как перечислить все поля класса в Python (и без методов)?

Предположим, что o - объект Python, и я хочу все поля o без каких-либо методов или __stuff__. Как это можно сделать?

Я пробовал такие вещи, как:

[f for f in dir(o) if not callable(f)]

[f for f in dir(o) if not inspect.ismethod(f)]

но они возвращают то же самое, что и dir(o), предположительно потому, что dir дает список строк. Кроме того, такие вещи, как __class__, будут возвращены сюда, даже если я получу это для работы.

Ответы

Ответ 1

Вы можете получить его с помощью атрибута __dict__ или встроенной vars функции, которая является просто ярлыком:

>>> class A(object):
...     foobar = 42
...     def __init__(self):
...         self.foo = 'baz'
...         self.bar = 3
...     def method(self, arg):
...         return True
...
>>> a = A()
>>> a.__dict__
{'foo': 'baz', 'bar': 3}
>>> vars(a)
{'foo': 'baz', 'bar': 3}

Есть только атрибуты объекта. Методов и атрибутов класса нет.

Ответ 2

Основной ответ: "вы не можете сделать это надежно". См. этот вопрос.

Вы можете получить приближение с помощью [attr for attr in dir(obj) if attr[:2] + attr[-2:] != '____' and not callable(getattr(obj,attr)].

Однако вы не должны полагаться на это, потому что:

Поскольку dir() предоставляется в первую очередь как удобство для использования в интерактивном приглашении, он пытается предоставить интересный набор имен больше, чем пытается предоставить строго или последовательно определенный набор имен, и его подробное поведение может измениться через выпуски.

Другими словами, нет никакого канонического способа получить список "всех атрибутов объекта" (или "все методы объекта" ).

Если вы выполняете какое-то динамическое программирование, которое требует от вас повторения полей unknwon объекта, единственный надежный способ сделать это - реализовать собственный способ отслеживания этих полей. Например, вы можете использовать соглашение об именах атрибутов или специальный объект "поля" или, проще говоря, словарь.

Ответ 3

Это должно работать для вызовов:

[f for f in dir(o) if not callable(getattr(o,f))]

Вы можете избавиться от остальных:

[f for f in dir(o) if not callable(getattr(o,f)) and not f.startswith('__')]

Ответ 4

Вы можете использовать встроенный метод vars()

Ответ 5

Вы можете перебирать атрибут __dict__ экземпляра и искать не-методы. Например:

CALLABLES = (types.FunctionType, types.MethodType)
for key, value in A().__dict__.items():
    if not isinstance(value, CALLABLES):
        print key

Вывод:

foo
bar

Вы можете сделать это в одном выражении со списком:

print [key for key, value in A.__dict__.items()
            if not isinstance(value, CALLABLES)]

Что бы напечатать ['foo', 'bar'].