How to enumerate an object's properties in Python?
Question:
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?
Answers:
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__
.
dir()
is the simple way. See here:
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.
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']
>>>
for one-liners:
print vars(theObject)
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']
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.
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).
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?
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__
.
dir()
is the simple way. See here:
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.
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']
>>>
for one-liners:
print vars(theObject)
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']
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.
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 optionalpredicate
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).