Getting attributes of a class
Getting attributes of a class
I want to get the attributes of a class, say:
class MyClass():
a = "12"
b = "34"
def myfunc(self):
return self.a
using MyClass.__dict__
gives me a list of attributes and functions, and even functions like __module__
and __doc__
. While MyClass().__dict__
gives me an empty dict unless I explicitly set an attribute value of that instance.
MyClass.__dict__
__module__
__doc__
MyClass().__dict__
I just want the attributes, in the example above those would be: a
and b
a
b
14 Answers
14
Try the inspect module. getmembers
and the various tests should be helpful.
getmembers
EDIT:
For example,
class MyClass(object):
a = '12'
b = '34'
def myfunc(self):
return self.a
>>> import inspect
>>> inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
[('__class__', type),
('__dict__',
<dictproxy '__dict__': <attribute '__dict__' of 'MyClass' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
'a': '34',
'b': '12',
'myfunc': <function __main__.myfunc>>),
('__doc__', None),
('__module__', '__main__'),
('__weakref__', <attribute '__weakref__' of 'MyClass' objects>),
('a', '34'),
('b', '12')]
Now, the special methods and attributes get on my nerves- those can be dealt with in a number of ways, the easiest of which is just to filter based on name.
>>> attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
>>> [a for a in attributes if not(a[0].startswith('__') and a[0].endswith('__'))]
[('a', '34'), ('b', '12')]
...and the more complicated of which can include special attribute name checks or even metaclasses ;)
yup this is great! I used this:
attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
print [a[0] for a in attributes if '_' not in a[0]]
– Mohamed Khamis
Jan 30 '12 at 10:09
attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
print [a[0] for a in attributes if '_' not in a[0]]
Be careful- that won't include attributes
like_this
! It'll also avoid "private" attributes, which you might've done on purpose.– Matt Luongo
Jan 30 '12 at 16:29
like_this
Hi, I loved that too with a slight clarification : in the expression
inspect.getmembers(MyClass, ...
, MyClass
can be replaced by a class or an object, and if you need the list of the values of your objects, you must replace MyClass
by your object variable (or self
if you put this expression in a def __repr__()
method like me).– geekobi
Sep 15 '17 at 20:23
inspect.getmembers(MyClass, ...
MyClass
MyClass
self
def __repr__()
def props(cls):
return [i for i in cls.__dict__.keys() if i[:1] != '_']
properties = props(MyClass)
This will include method names
– lenhhoxung
Jul 1 '16 at 9:41
Woudn't be more clear to check:
if not i.startswith('_')
instead of if i[:1] != '_'
?– Mikaelblomkvistsson
Nov 25 '17 at 15:08
if not i.startswith('_')
if i[:1] != '_'
myfunc
is an attribute of MyClass
. That's how it's found when you run:
myfunc
MyClass
myinstance = MyClass()
myinstance.myfunc()
It looks for an attribute on myinstance
named myfunc
, doesn't find one, sees that myinstance
is an instance of MyClass
and looks it up there.
myinstance
myfunc
myinstance
MyClass
So the complete list of attributes for MyClass
is:
MyClass
>>> dir(MyClass)
['__doc__', '__module__', 'a', 'b', 'myfunc']
(Note that I'm using dir just as a quick and easy way to list the members of the class: it should only be used in an exploratory fashion, not in production code)
If you only want particular attributes, you'll need to filter this list using some criteria, because __doc__
, __module__
, and myfunc
aren't special in any way, they're attributes in exactly the same way that a
and b
are.
__doc__
__module__
myfunc
a
b
I've never used the inspect module referred to by Matt and Borealid, but from a brief link it looks like it has tests to help you do this, but you'll need to write your own predicate function, since it seems what you want is roughly the attributes that don't pass the isroutine
test and don't start and end with two underscores.
isroutine
Also note: by using class MyClass():
in Python 2.7 you're using the wildly out of date old-style classes. Unless you're doing so deliberately for compatibility with extremely old libraries, you should be instead defining your class as class MyClass(object):
. In Python 3 there are no "old-style" classes, and this behaviour is the default. However, using newstyle classes will get you a lot more automatically defined attributes:
class MyClass():
class MyClass(object):
>>> class MyClass(object):
a = "12"
b = "34"
def myfunc(self):
return self.a
>>> dir(MyClass)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'myfunc']
One cannot depend on
dir()
: "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." (see documentation of dir()
).– Tadeck
Jan 30 '12 at 1:31
dir()
dir()
@Tadeck: Good point. I was using it illustratively rather than suggesting it as a solution, since it wouldn't easily allow you to filter the attributes based on what they refer to. But I should be more explicit about that.
– Ben
Jan 30 '12 at 2:02
MyClass().__class__.__dict__
MyClass().__class__.__dict__
However, the "right" was to do this is via the inspect module.
MyClass().__class__.__dict__
== MyClass.__dict__
– yak
Jan 30 '12 at 4:03
MyClass().__class__.__dict__
MyClass.__dict__
@yak's comment isn't quite true. See the following about the differences between class and instance attributes. See stackoverflow.com/questions/35805/….
– sholsapp
Feb 16 '15 at 18:33
I don't know if something similar has been made by now or not, but I made a nice attribute search function using vars(). vars() creates a dictionary of the attributes of a class you pass through it.
class Player():
def __init__(self):
self.name = 'Bob'
self.age = 36
self.gender = 'Male'
s = vars(Player())
#From this point if you want to print all the attributes, just do print(s)
#If the class has a lot of attributes and you want to be able to pick 1 to see
#run this function
def play():
ask = input("What Attribute?>: ")
for key, value in s.items():
if key == ask:
print("self. = ".format(key, value))
break
else:
print("Couldn't find an attribute for self.".format(ask))
I'm developing a pretty massive Text Adventure in Python, my Player class so far has over 100 attributes. I use this to search for specific attributes I need to see.
My solution to get all attributes (not methods) of a class
def get_class_attrs(cls):
return re.findall(r'w+(?=[,)])', cls.__dict__['__doc__'])
I recently needed to figure out something similar to this question, so I wanted to post some background info that might be helpful to others facing the same in future.
Here's how it works in Python (from https://docs.python.org/3.5/reference/datamodel.html#the-standard-type-hierarchy):
MyClass
is a class object, MyClass()
is an instance of the class object. An instance's __dict__
only hold attributes and methods specific to that instance (e.g. self.somethings
). If an attribute or method is part of a class, it is in the class's __dict__
. When you do MyClass().__dict__
, an instance of MyClass
is created with no attributes or methods besides the class attributes, thus the empty __dict__
MyClass
MyClass()
__dict__
self.somethings
__dict__
MyClass().__dict__
MyClass
__dict__
So if you say print(MyClass().b)
, Python first checks the new instance's dict MyClass().__dict__['b']
and fails to find b
. It then checks the class MyClass.__dict__['b']
and finds b
.
print(MyClass().b)
MyClass().__dict__['b']
b
MyClass.__dict__['b']
b
That's why you need the inspect
module, to emulate that same search process.
inspect
Scott - A comment posted as an answer must get deleted, otherwise we'd be drowning in them. However, a partial answer or "helpful nudge" towards a solution is still an answer. You'll see how I reworded your post; hopefully I retained your intent. If not, you can further edit it into shape. Cheers!
– Mogsdad
Mar 9 '16 at 18:35
import re
class MyClass:
a = "12"
b = "34"
def myfunc(self):
return self.a
attributes = [a for a, v in MyClass.__dict__.items()
if not re.match('<function.*?>', str(v))
and not (a.startswith('__') and a.endswith('__'))]
For an instance of MyClass, such as
mc = MyClass()
use type(mc)
in place of MyClass
in the list comprehension. However, if one dynamically adds an attribute to mc
, such as mc.c = "42"
, the attribute won't show up when using type(mc)
in this strategy. It only gives the attributes of the original class.
type(mc)
MyClass
mc
mc.c = "42"
type(mc)
To get the complete dictionary for a class instance, you would need to COMBINE the dictionaries of type(mc).__dict__
and mc.__dict__
.
type(mc).__dict__
mc.__dict__
mc = MyClass()
mc.c = "42"
# Python 3.5
combined_dict = **type(mc).__dict__, **mc.__dict__
# Or Python < 3.5
def dict_union(d1, d2):
z = d1.copy()
z.update(d2)
return z
combined_dict = dict_union(type(mc).__dict__, mc.__dict__)
attributes = [a for a, v in combined_dict.items()
if not re.match('<function.*?>', str(v))
and not (a.startswith('__') and a.endswith('__'))]
Really neat solution.
– Liliane
Aug 12 '17 at 20:20
Getting only the instance attributes is easy.
But getting also the class attributes without the functions is a bit more tricky.
Instance attributes only
If you only have to list instance attributes just usefor attribute, value in my_instance
.__dict__
.items()
for attribute, value in my_instance
__dict__
items()
>>> from __future__ import (absolute_import, division, print_function)
>>> class MyClass(object):
... def __init__(self):
... self.a = 2
... self.b = 3
... def print_instance_attributes(self):
... for attribute, value in self.__dict__.items():
... print(attribute, '=', value)
...
>>> my_instance = MyClass()
>>> my_instance.print_instance_attributes()
a = 2
b = 3
>>> for attribute, value in my_instance.__dict__.items():
... print(attribute, '=', value)
...
a = 2
b = 3
Instance and class attributes
To get also the class attributes without the functions, the trick is to use callable()
.
callable()
But static methods are not always callable
!
callable
Therefore, instead of using callable(value)
usecallable
(getattr
(MyClass, attribute))
callable(value)
callable
getattr
MyClass, attribute))
from __future__ import (absolute_import, division, print_function)
class MyClass(object):
a = "12"
b = "34" # class attributes
def __init__(self, c, d):
self.c = c
self.d = d # instance attributes
@staticmethod
def mystatic(): # static method
return MyClass.b
def myfunc(self): # non-static method
return self.a
def print_instance_attributes(self):
print('[instance attributes]')
for attribute, value in self.__dict__.items():
print(attribute, '=', value)
def print_class_attributes(self):
print('[class attributes]')
for attribute in MyClass.__dict__.keys():
if attribute[:2] != '__':
value = getattr(MyClass, attribute)
if not callable(value):
print(attribute, '=', value)
v = MyClass(4,2)
v.print_class_attributes()
v.print_instance_attributes()
Note: print_class_attributes()
should be @staticmethod
but not in this stupid and simple example.
print_class_attributes()
@staticmethod
$ python2 ./print_attributes.py
[class attributes]
a = 12
b = 34
[instance attributes]
c = 4
d = 2
$ python3 ./print_attributes.py
[class attributes]
b = 34
a = 12
[instance attributes]
c = 4
d = 2
There is a very simple answer, that should be obvious: getattr
class MyClass(object):
a = '12'
b = '34'
def myfunc(self):
return self.a
>>> getattr(MyClass, 'a')
'12'
>>> getattr(MyClass, 'myfunc')
<function MyClass.myfunc at 0x10de45378>
It works dandy both in Python 2.7 and Python 3.x.
If you want a list of these items, you will still need to use inspect.
You can use dir()
in a list comprehension to get the attribute names:
dir()
names = [p for p in dir(myobj) if not p.startswith('_')]
Use getattr()
to get the attributes themselves:
getattr()
attrs = [getattr(myobj, p) for p in dir(myobj) if not p.startswith('_')]
This can be done without inspect, I guess.
Take the following class:
class Test:
a = 1
b = 2
def __init__(self):
self.c = 42
@staticmethod
def toto():
return "toto"
def test(self):
return "test"
Looking at the members along with their types:
t = Test()
l = [ (x, eval('type(x.%s).__name__' % x)) for x in dir(a) ]
... gives:
[('__doc__', 'NoneType'),
('__init__', 'instancemethod'),
('__module__', 'str'),
('a', 'int'),
('b', 'int'),
('c', 'int'),
('test', 'instancemethod'),
('toto', 'function')]
So to output only the variables, you just have to filter the results by type, and names not starting with '__'. E.g.
filter(lambda x: x[1] not in ['instancemethod', 'function'] and not x[0].startswith('__'), l)
[('a', 'int'), ('b', 'int'), ('c', 'int')] # actual result
That's it.
Note: if you're using Python 3, convert the iterators to lists.
If you want a more robust way to do it, use inspect.
two function:
def get_class_attr(Cls) -> :
import re
return [a for a, v in Cls.__dict__.items()
if not re.match('<function.*?>', str(v))
and not (a.startswith('__') and a.endswith('__'))]
def get_class_attr_val(cls):
attr = get_class_attr(type(cls))
attr_dict =
for a in attr:
attr_dict[a] = getattr(cls, a)
return attr_dict
use:
>>> class MyClass:
a = "12"
b = "34"
def myfunc(self):
return self.a
>>> m = MyClass()
>>> get_class_attr_val(m)
'a': '12', 'b': '34'
I know this was three years ago, but for those who are to come by this question in the future, for me:
class_name.attribute
works just fine.
except when you get an AttributeError.
– rady
May 28 '15 at 21:40
You don't always know what
attribute
is beforehand.– Matt Luongo
Aug 31 '15 at 19:38
attribute
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
possible duplicate of Inspect python class attributes
– Ciro Santilli 新疆改造中心 六四事件 法轮功
Mar 25 '14 at 14:34