88

Suppose o is a Python object, and I want all of the fields of o, without any methods or __stuff__. How can this be done?

I've tried things like:

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

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

but these return the same as dir(o), presumably because dir gives a list of strings. Also, things like __class__ would be returned here, even if I get this to work.

martineau
  • 119,623
  • 25
  • 170
  • 301
Eric Wilson
  • 57,719
  • 77
  • 200
  • 270

6 Answers6

112

You can get it via the __dict__ attribute, or the built-in vars function, which is just a shortcut:

>>> 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}

There's only attributes of the object. Methods and class attributes aren't present.

Maxime Lorant
  • 34,607
  • 19
  • 87
  • 97
  • 8
    This is per-instance. – 2rs2ts Feb 21 '14 at 21:04
  • 6
    This is probably the best approximation you're going to get, but it should be noted that this considers callable instance attributes (which are sometimes used and are effectively like methods) as non-methods and considers class attributes with no corresponding instance attribute not a field (even though it acts like one for most purposes). It also ignores properties and fails on classes with `__slots__`, which may or may not matter. –  Feb 21 '14 at 21:06
  • 3
    also doesn't work if __dict __ is not defined. which it isn't always. – John Sohn Sep 21 '21 at 17:00
  • __slots__ doesn't always contain everything you're looking for either. – John Sohn Sep 21 '21 at 17:00
22

You could use the built-in method vars()

El Bert
  • 2,958
  • 1
  • 28
  • 36
  • 1
    I'm in favor of calling other methods instead of mangled magic methods and properties in Python. I think this is much more Pythonic way. So, take my +1. – Eray Erdin Apr 28 '19 at 01:01
  • 1
    Traceback (most recent call last): File "", line 1, in TypeError: vars() argument must have __dict__ attribute – John Sohn Sep 21 '21 at 17:01
  • @JohnSohn hard to figure out the issue from just the error message but it is telling us that whatever is passed to `vars()` doesn't have a `__dict__` attribute indicating that what's passed probably isn't an `object`. And indeed with `a = "text"; vars(a)` we get a similar message. – El Bert Sep 24 '21 at 14:28
15

The basic answer is "you can't do so reliably". See this question.

You can get an approximation with [attr for attr in dir(obj) if attr[:2] + attr[-2:] != '____' and not callable(getattr(obj,attr))].

However, you shouldn't rely on this, because:

Because dir() is supplied primarily as a convenience for use at an interactive prompt, it tries to supply an interesting set of names more than it tries to supply a rigorously or consistently defined set of names, and its detailed behavior may change across releases.

In other words, there is no canonical way to get a list of "all of an object's attributes" (or "all of an object's methods").

If you're doing some kind of dynamic programming that requires you to iterate over unknwon fields of an object, the only reliable way to do it is to implement your own way of keeping track of those fields. For instance, you could use an attribute naming convention, or a special "fields" object, or, most simply, a dictionary.

Ollie
  • 1,641
  • 1
  • 13
  • 31
BrenBarn
  • 242,874
  • 37
  • 412
  • 384
  • I'm not sure, but if you can create your own members surrounded by double underscores, this'll break. – 2rs2ts Feb 21 '14 at 21:07
  • 3
    @2rs2ts: Yes, that is true. There is no way around that. There's no way to programatically tell if a double-underscore name is "magic" or not; you have to read the documentation. – BrenBarn Feb 21 '14 at 21:08
  • 3
    These are naming conventions, you shouldn't create your own members by surrounding them with double underscores. – Benjamin Toueg Feb 21 '14 at 21:11
  • @Benjamin: Indeed. At the end of the [**Descriptive: Naming Styles**](https://www.python.org/dev/peps/pep-0008/#descriptive-naming-styles) section of [PEP 8 - Style Guide for Python Code](https://www.python.org/dev/peps/pep-0008/), regarding names with both double-underscore-prefix & suffixes, it says "Never invent such names; only use them as documented." – martineau Feb 18 '18 at 16:25
  • I'm starting to find myself in agreement with this. – John Sohn Sep 21 '21 at 17:01
10

This should work for callables:

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

You could get rid of the rest with:

[f for f in dir(o) if not callable(getattr(o,f)) and not f.startswith('__')]
Benjamin Toueg
  • 10,511
  • 7
  • 48
  • 79
7

You can iterate through an instance's __dict__ attribute and look for non-method things. For example:

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

Output:

foo
bar

You can do it in a single statement with a list comprehension:

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

Which would print ['foo', 'bar'].

martineau
  • 119,623
  • 25
  • 170
  • 301
  • There's no need to filter out methods, since they're in the class `__dict__`, not the instance `__dict__`s. – Blckknght Feb 21 '14 at 21:58
  • @Blckknght: I put the test in because a class is an object, too. However, I realized after your comment the need to check for than one type of callable, and have modified my answer. Thanks. If one can assume that the object is a new-style class instance, then what you said is true and the `for` loops could be simplified. – martineau Feb 21 '14 at 22:25
-2

You can get it via fields attribute: o._fields_

Julia Meshcheryakova
  • 3,162
  • 3
  • 22
  • 42
ENEG
  • 1