189

I C# we do it through reflection. In Javascript it is simple as:

for(var propertyName in objectName)
    var currentPropertyValue = objectName[propertyName];

How to do it in Python?

Jader Dias
  • 88,211
  • 155
  • 421
  • 625
  • 1
    linking this: [How do you get list of methods in a python class?](http://stackoverflow.com/questions/1911281/how-do-you-get-list-of-methods-in-a-python-class) – ジョージ Apr 25 '12 at 10:32
  • 9
    Please note that this question is a misnomer. Most answers are about enumerating *members*. I was looking for a way to enumerate *properties*, i.e. members of a class decorated with `@property`. – Tomasz Gandor May 13 '19 at 04:18

8 Answers8

215
for property, value in vars(theObject).items():
    print(property, ":", value)

Be aware that in some rare cases there's a __slots__ property, such classes often have no __dict__.

Georg Schölly
  • 124,188
  • 49
  • 220
  • 267
  • 1
    now how to change the value? in Javascript you could do: object[property] = newValue. How to do it in Python? – Jader Dias Aug 09 '09 at 18:32
  • I got it: objectName.__dict__[propertyName] = newValue – Jader Dias Aug 09 '09 at 19:03
  • 1
    @Nelson Could you elaborate why that's a better option? Is it just shorter, or are there additional considerations? – WhyNotHugo Jun 06 '14 at 16:56
  • 8
    @Hugo: First because it's "pythonic", in other words that's the syntax a large majority of the community is expecting to see. The other syntax would likely unnecessarily give pause to anyone reading your code. Second, some types implement a setter `__setattr__()`. Setting values directly on the dictionary bypasses the object's setter (and/or its parents'). It's quite common in python that more things than meet the eye are happening in the background during attribute setting (e.g. sanitation), using `setattr()` ensures that you don't miss out, or are forced to handle them explicitly yourself. – Michael Ekoka Sep 07 '14 at 21:13
  • 3
    @Hi-Angel That _does_ work. What isn't working, however, is the constellation of preconceptions and assumptions you have surrounding status versus dynamic object members in Python. `vars()` only returns **static members** (i.e., object attributes and methods registered with that object's `__dict__`). It does _not_ return **dynamic members** (i.e., object attributes and methods dynamically defined by that object's `__getattr__()` method or similar magic). In all likelihood, your desired `file.ImplementationName` property is defined dynamically and hence _not_ available to `vars()` or `dir()`. – Cecil Curry Feb 02 '16 at 04:18
  • 3
    @CecilCurry dude, while I appreciate your enlightening comment, I don't appreciate your sarcasm. What you just said is neither obvious, nor easy to find unless one knows language internals enough to not ask it here. It ought to be mentioned in the answer. – Hi-Angel Feb 02 '16 at 10:11
  • So what happens if we have a `__slots__` property? Is `dir` the only way then? – information_interchange May 17 '19 at 15:05
  • @information_interchange You can look at the `__slots__` attribute and parse it yourself: `class T(): __slots__ = ["a", "b"]; t = T(); print(t.__slots__)` – Georg Schölly May 20 '19 at 08:02
  • Well, it does not work: AttributeError: 'dict' object has no attribute 'iteritems' – Matej J Aug 24 '20 at 19:17
  • @MatejJ `.iteritems()` only exist in Python 2, for Python 3 you should use `.items()` instead. – Georg Schölly Aug 25 '20 at 08:56
91

dir() is the simple way. See here:

Guide To Python Introspection

oPless
  • 618
  • 1
  • 8
  • 18
EBGreen
  • 36,735
  • 12
  • 65
  • 85
  • 6
    Something to note from the Python docs, _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. For example, metaclass attributes are not in the result list when the argument is a class._ – skyler Jan 26 '15 at 14:06
73

See inspect.getmembers(object[, predicate]).

Return all the members of an object in a list of (name, value) pairs sorted by name. If the optional predicate argument is supplied, only members for which the predicate returns a true value are included.

>>> [name for name,thing in inspect.getmembers([])]
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', 
'__delslice__',    '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', 
'__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', 
'__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__','__reduce_ex__', 
'__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', 
'__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 
'insert', 'pop', 'remove', 'reverse', 'sort']
>>> 
gimel
  • 83,368
  • 10
  • 76
  • 104
  • Yeah, this answer is great; never used this module before. getmembers() is implemented by just walking the results of dir(object), btw. – Nelson Aug 09 '09 at 17:53
  • Can you elaborate why this is better than accessing __dict__? The Python documentation is less than helpful, especially because normally it uses the term `attributes` instead of `members` (is there any difference between the two?). They could have fixed the name in Python 3.0 to make it consistent. – nikow Aug 09 '09 at 20:56
  • Oops, meant `__dict__`, sorry. – nikow Aug 09 '09 at 20:57
  • 4
    @nikow: inspect.getmembers() is guaranteed to keep working even if the internal details change. – Georg Schölly Aug 09 '09 at 21:30
  • Could someone clarify, does inspect.getmembers() differ fundamentally from dir(), or is it just a convenient wrapper around dir (which the "Note:" in its documentation implies might be the case)? – Nicholas Knight Jan 01 '10 at 11:27
  • Hm… Seems that it should work, but for some reason it throws `inspect.UnknownPropertyException`. – Hi-Angel Aug 22 '15 at 11:18
  • 3
    @NicholasKnight `inspect.getmembers()` wraps `dir()` with the (mostly negligible) side benefits of **(A)** including [dynamic class attributes](https://docs.python.org/3/library/types.html#types.DynamicClassAttribute) and [metaclass attributes](http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python) and **(B)** excluding members _not_ matching the passed predicate. _Yawn, right?_ `inspect.getmembers()` is appropriate for third-party libraries generically supporting all possible object types. For standard use cases, however, `dir()` absolutely suffices. – Cecil Curry Feb 02 '16 at 04:44
20

The __dict__ property of the object is a dictionary of all its other defined properties. Note that Python classes can override getattr and make things that look like properties but are not in__dict__. There's also the builtin functions vars() and dir() which are different in subtle ways. And __slots__ can replace __dict__ in some unusual classes.

Objects are complicated in Python. __dict__ is the right place to start for reflection-style programming. dir() is the place to start if you're hacking around in an interactive shell.

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
Nelson
  • 27,541
  • 5
  • 35
  • 31
18

for one-liners:

print vars(theObject)
Nicolas Rojo
  • 703
  • 1
  • 7
  • 14
13

If you're looking for reflection of all properties, the answers above are great.

If you're simply looking to get the keys of a dictionary (which is different from an 'object' in Python), use

my_dict.keys()

my_dict = {'abc': {}, 'def': 12, 'ghi': 'string' }
my_dict.keys() 
> ['abc', 'def', 'ghi']
MrE
  • 19,584
  • 12
  • 87
  • 105
  • 2
    even though it's my answer, I don't think it should be the accepted answer: the keys of an object are different from the property of an object instance of a class. They're accessed differently (`obj['key']` vs. `obj.property`) and the question was about object properties. I put my answer here because there is easy confusion between the two. – MrE Feb 17 '18 at 16:34
  • 1
    I would actually suggest removing this answer. – Ente Nov 22 '19 at 07:47
  • As stated above, people coming from Javascript or C# for example are easily confused by the terminology as there is no difference between those 2 concepts. People learning python and trying to access keys are very likely to search for 'properties' and end up here, hence why I think it belongs. – MrE Dec 12 '19 at 18:21
  • and you are right, but miss the point: in other languages (take JS) there is no distinction between object and dictionary. The OP comes from C# asking the question. This answer, although wrong, got 11 upvotes, proof that people who land here find it useful, even though it is not technically the right answer (as I point out) to the question when looking at it in strict python lingo. I'll edit to make it even more crystal clear. – MrE Dec 13 '19 at 07:21
12

This is totally covered by the other answers, but I'll make it explicit. An object may have class attributes and static and dynamic instance attributes.

class foo:
    classy = 1
    @property
    def dyno(self):
        return 1
    def __init__(self):
        self.stasis = 2

    def fx(self):
        return 3

stasis is static, dyno is dynamic (cf. property decorator) and classy is a class attribute. If we simply do __dict__ or vars we will only get the static one.

o = foo()
print(o.__dict__) #{'stasis': 2}
print(vars(o)) #{'stasis': 2}

So if we want the others __dict__ will get everything (and more). This includes magic methods and attributes and normal bound methods. So lets avoid those:

d = {k: getattr(o, k, '') for k in o.__dir__() if k[:2] != '__' and type(getattr(o, k, '')).__name__ != 'method'}
print(d) #{'stasis': 2, 'classy': 1, 'dyno': 1}

The type called with a property decorated method (a dynamic attribute) will give you the type of the returned value, not method. To prove this let's json stringify it:

import json
print(json.dumps(d)) #{"stasis": 2, "classy": 1, "dyno": 1}

Had it been a method it would have crashed.

TL;DR. try calling extravar = lambda o: {k: getattr(o, k, '') for k in o.__dir__() if k[:2] != '__' and type(getattr(o, k, '')).__name__ != 'method'} for all three, but not methods nor magic.

jjmerelo
  • 22,578
  • 8
  • 40
  • 86
Matteo Ferla
  • 2,128
  • 1
  • 16
  • 27
4

I think it's worth showing the difference between the various options mentioned - often a picture is worth a thousand words.

>>> from pprint import pprint
>>> import inspect
>>>
>>> class a():
    x = 1               # static class member
    def __init__(self):
        self.y = 2      # static instance member
    @property
    def dyn_prop(self): # dynamic property
        print('DYNPROP WAS HERE')
        return 3
    def test(self):     # function member
        pass
    @classmethod
    def myclassmethod(cls): # class method; static methods behave the same
        pass

>>> i = a()
>>> pprint(i.__dict__)
{'y': 2}
>>> pprint(vars(i))
{'y': 2}
>>> pprint(dir(i))
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'dyn_prop',
 'myclassmethod',
 'test',
 'x',
 'y']
>>> pprint(inspect.getmembers(i))
DYNPROP WAS HERE
[('__class__', <class '__main__.a'>),
 ('__delattr__',
  <method-wrapper '__delattr__' of a object at 0x000001CB891BC7F0>),
 ('__dict__', {'y': 2}),
 ('__dir__', <built-in method __dir__ of a object at 0x000001CB891BC7F0>),
 ('__doc__', None),
 ('__eq__', <method-wrapper '__eq__' of a object at 0x000001CB891BC7F0>),
 ('__format__', <built-in method __format__ of a object at 0x000001CB891BC7F0>),
 ('__ge__', <method-wrapper '__ge__' of a object at 0x000001CB891BC7F0>),
 ('__getattribute__',
  <method-wrapper '__getattribute__' of a object at 0x000001CB891BC7F0>),
 ('__gt__', <method-wrapper '__gt__' of a object at 0x000001CB891BC7F0>),
 ('__hash__', <method-wrapper '__hash__' of a object at 0x000001CB891BC7F0>),
 ('__init__',
  <bound method a.__init__ of <__main__.a object at 0x000001CB891BC7F0>>),
 ('__init_subclass__',
  <built-in method __init_subclass__ of type object at 0x000001CB87CA6A70>),
 ('__le__', <method-wrapper '__le__' of a object at 0x000001CB891BC7F0>),
 ('__lt__', <method-wrapper '__lt__' of a object at 0x000001CB891BC7F0>),
 ('__module__', '__main__'),
 ('__ne__', <method-wrapper '__ne__' of a object at 0x000001CB891BC7F0>),
 ('__new__', <built-in method __new__ of type object at 0x00007FFCA630AB50>),
 ('__reduce__', <built-in method __reduce__ of a object at 0x000001CB891BC7F0>),
 ('__reduce_ex__',
  <built-in method __reduce_ex__ of a object at 0x000001CB891BC7F0>),
 ('__repr__', <method-wrapper '__repr__' of a object at 0x000001CB891BC7F0>),
 ('__setattr__',
  <method-wrapper '__setattr__' of a object at 0x000001CB891BC7F0>),
 ('__sizeof__', <built-in method __sizeof__ of a object at 0x000001CB891BC7F0>),
 ('__str__', <method-wrapper '__str__' of a object at 0x000001CB891BC7F0>),
 ('__subclasshook__',
  <built-in method __subclasshook__ of type object at 0x000001CB87CA6A70>),
 ('__weakref__', None),
 ('dyn_prop', 3),
 ('myclassmethod', <bound method a.myclassmethod of <class '__main__.a'>>),
 ('test', <bound method a.test of <__main__.a object at 0x000001CB891BC7F0>>),
 ('x', 1),
 ('y', 2)]

To summarize:

  • vars() and __dict__ only return instance-local properties;
  • dir() returns everything, but only as a list of string member names; dynamic properties are not called;
  • inspect.getmembers() returns everything, as a list of tuples (name, value); it actually runs dynamic properties, and accepts an optional predicate argument that can filter out members by value.

So my common-sense approach is typically to use dir() on the command line, and getmembers() in programs, unless specific performance considerations apply.

Note that, to keep things cleaner, I did not include __slots__ - if present, it was explicitly put there to be queried, and should be used directly. I also did not cover metaclasses, which can get a bit hairy (most people will never use them anyway).

Giacomo Lacava
  • 1,784
  • 13
  • 25