List attributes of an object

PythonClassPython 3.x

Python Problem Overview


Is there a way to grab a list of attributes that exist on instances of a class?

class new_class():
    def __init__(self, number):
        self.multi = int(number) * 2
        self.str = str(number)

a = new_class(2)
print(', '.join(a.SOMETHING))

The desired result is that "multi, str" will be output. I want this to see the current attributes from various parts of a script.

Python Solutions


Solution 1 - Python

>>> class new_class():
...   def __init__(self, number):
...     self.multi = int(number) * 2
...     self.str = str(number)
... 
>>> a = new_class(2)
>>> a.__dict__
{'multi': 4, 'str': '2'}
>>> a.__dict__.keys()
dict_keys(['multi', 'str'])

You may also find pprint helpful.

Solution 2 - Python

dir(instance)
# or (same value)
instance.__dir__()
# or
instance.__dict__

Then you can test what type is with type() or if is a method with callable().

Solution 3 - Python

All previous answers are correct, you have three options for what you are asking

  1. [dir()][1]

  2. [vars()][2]

  3. [__dict__][3]

>>> dir(a)
['__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__', 'multi', 'str']
>>> vars(a)
{'multi': 4, 'str': '2'}
>>> a.__dict__
{'multi': 4, 'str': '2'}

[1]: https://docs.python.org/3/library/functions.html#dir "dir()" [2]: https://docs.python.org/3/library/functions.html#vars [3]: https://docs.python.org/3/library/stdtypes.html#object.__dict__ "dict"

Solution 4 - Python

vars(obj) returns the attributes of an object.

Solution 5 - Python

Inspect module:

> The inspect module provides several useful functions to help get > information about live objects such as modules, classes, methods, > functions, tracebacks, frame objects, and code objects.


Using getmembers() you can see all attributes of your class, along with their value. To exclude private or protected attributes use .startswith('_'). To exclude methods or functions use inspect.ismethod() or inspect.isfunction().

import inspect


class NewClass(object):
    def __init__(self, number):
        self.multi = int(number) * 2
        self.str = str(number)

    def func_1(self):
        pass


inst = NewClass(2)

for i in inspect.getmembers(inst):
    # Ignores anything starting with underscore 
    # (that is, private and protected attributes)
    if not i[0].startswith('_'):
        # Ignores methods
        if not inspect.ismethod(i[1]):
            print(i)

Note that ismethod() is used on the second element of i since the first is simply a string (its name).

Offtopic: Use CamelCase for class names.

Solution 6 - Python

>>> ', '.join(i for i in dir(a) if not i.startswith('__'))
'multi, str'

This of course will print any methods or attributes in the class definition. You can exclude "private" methods by changing i.startwith('__') to i.startwith('_')

Solution 7 - Python

You can use dir(your_object) to get the attributes and getattr(your_object, your_object_attr) to get the values

usage :

for att in dir(your_object):
    print (att, getattr(your_object,att))

This is particularly useful if your object have no _dict_. If that is not the case you can try var(your_object) also

Solution 8 - Python

It's often mentioned that to list a complete list of attributes you should use dir(). Note however that contrary to popular belief dir() does not bring out all attributes. For example you might notice that __name__ might be missing from a class's dir() listing even though you can access it from the class itself. From the doc on dir() (Python 2, Python 3):

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

A function like the following tends to be more complete, although there's no guarantee of completeness since the list returned by dir() can be affected by many factors including implementing the __dir__() method, or customizing __getattr__() or __getattribute__() on the class or one of its parents. See provided links for more details.

def dirmore(instance):
    visible = dir(instance)
    visible += [a for a in set(dir(type)).difference(visible)
                if hasattr(instance, a)]
    return sorted(visible)

Solution 9 - Python

There is more than one way to do it:

#! /usr/bin/env python3
#
# This demonstrates how to pick the attiributes of an object

class C(object) :

  def __init__ (self, name="q" ):
    self.q = name
    self.m = "y?"

c = C()

print ( dir(c) )

When run, this code produces:

jeffs@jeff-desktop:~/skyset$ python3 attributes.py 
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__',      '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'm', 'q']

jeffs@jeff-desktop:~/skyset$

Solution 10 - Python

What do you want this for? It may be hard to get you the best answer without knowing your exact intent.

  • It is almost always better to do this manually if you want to display an instance of your class in a specific way. This will include exactly what you want and not include what you don't want, and the order will be predictable.

    If you are looking for a way to display the content of a class, manually format the attributes you care about and provide this as the __str__ or __repr__ method for your class.

  • If you want to learn about what methods and such exist for an object to understand how it works, use help. help(a) will show you a formatted output about the object's class based on its docstrings.

  • dir exists for programatically getting all the attributes of an object. (Accessing __dict__ does something I would group as the same but that I wouldn't use myself.) However, this may not include things you want and it may include things you do not want. It is unreliable and people think they want it a lot more often than they do.

  • On a somewhat orthogonal note, there is very little support for Python 3 at the current time. If you are interested in writing real software you are going to want third-party stuff like numpy, lxml, Twisted, PIL, or any number of web frameworks that do not yet support Python 3 and do not have plans to any time too soon. The differences between 2.6 and the 3.x branch are small, but the difference in library support is huge.

Solution 11 - Python

Please see the python shell script which has been executed in sequence, here you will get the attributes of a class in string format separated by comma.

>>> class new_class():
...     def __init__(self, number):
...         self.multi = int(number)*2
...         self.str = str(number)
... 
>>> a = new_class(4)
>>> ",".join(a.__dict__.keys())
'str,multi'<br/>

I am using python 3.4

Solution 12 - Python

In addition to these answers, I'll include a function (python 3) for spewing out virtually the entire structure of any value. It uses dir to establish the full list of property names, then uses getattr with each name. It displays the type of every member of the value, and when possible also displays the entire member:

import json

def get_info(obj):
  
  type_name = type(obj).__name__
  print('Value is of type {}!'.format(type_name))
  prop_names = dir(obj)

  for prop_name in prop_names:
    prop_val = getattr(obj, prop_name)
    prop_val_type_name = type(prop_val).__name__
    print('{} has property "{}" of type "{}"'.format(type_name, prop_name, prop_val_type_name))
  
    try:
      val_as_str = json.dumps([ prop_val ], indent=2)[1:-1]
      print('  Here\'s the {} value: {}'.format(prop_name, val_as_str))
    except:
      pass

Now any of the following should give insight:

get_info(None)
get_info('hello')

import numpy
get_info(numpy)
# ... etc.

Solution 13 - Python

Get attributes of an object

class new_class():
    def __init__(self, number):
	self.multi = int(number) * 2
	self.str = str(number)

new_object = new_class(2)                
print(dir(new_object))                   #total list attributes of new_object
attr_value = new_object.__dict__         
print(attr_value)                        #Dictionary of attribute and value for new_class                   

for attr in attr_value:                  #attributes on  new_class
	print(attr)

Output

['__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__', 'multi', 'str']

{'multi': 4, 'str': '2'}

multi
str

Solution 14 - Python

As written before using obj.__dict__ can handle common cases but some classes do not have the __dict__ attribute and use __slots__ (mostly for memory efficiency).

example for a more resilient way of doing this:

class A(object):
    __slots__ = ('x', 'y', )
    def __init__(self, x, y):
        self.x = x
        self.y = y


class B(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y


def get_object_attrs(obj):
    try:
        return obj.__dict__
    except AttributeError:
        return {attr: getattr(obj, attr) for attr in obj.__slots__}


a = A(1,2)
b = B(1,2)
assert not hasattr(a, '__dict__')

print(get_object_attrs(a))
print(get_object_attrs(b))

this code's output:

{'x': 1, 'y': 2}
{'x': 1, 'y': 2}

Note1:
Python is a dynamic language and it is always better knowing the classes you trying to get the attributes from as even this code can miss some cases.

Note2:
this code outputs only instance variables meaning class variables are not provided. for example:

class A(object):
    url = 'http://stackoverflow.com'
    def __init__(self, path):
        self.path = path

print(A('/questions').__dict__)

code outputs:

{'path': '/questions'}

This code does not print the url class attribute and might omit wanted class attributes.
Sometimes we might think an attribute is an instance member but it is not and won't be shown using this example.

Solution 15 - Python

  • Using __dict__ or vars does not work because it misses out __slots__.
  • Using __dict__ and __slots__ does not work because it misses out __slots__ from base classes.
  • Using dir does not work because it includes class attributes, such as methods or properties, as well as the object attributes.
  • Using vars is equivalent to using __dict__.

This is the best I have:

from typing import Dict

def get_attrs( x : object ) -> Dict[str, object]:
    mro      = type( x ).mro()
    attrs    = { }
    has_dict = False
    sentinel = object()
    
    for klass in mro:
        for slot in getattr( klass, "__slots__", () ):
            v = getattr( x, slot, sentinel )
            
            if v is sentinel:
                continue
            
            if slot == "__dict__":
                assert not has_dict, "Multiple __dicts__?"
                attrs.update( v )
                has_dict = True
            else:
                attrs[slot] = v
    
    if not has_dict:
        attrs.update( getattr( x, "__dict__", { } ) )
    
    return attrs

Solution 16 - Python

Please see the following Python shell scripting execution in sequence, it will give the solution from creation of class to extracting the field names of instances.

>>> class Details:
...       def __init__(self,name,age):
...           self.name=name
...           self.age =age
...       def show_details(self):
...           if self.name:
...              print "Name : ",self.name
...           else:
...              print "Name : ","_"
...           if self.age:
...              if self.age>0:
...                 print "Age  : ",self.age
...              else:
...                 print "Age can't be -ve"
...           else:
...              print "Age  : ","_"
... 
>>> my_details = Details("Rishikesh",24)
>>> 
>>> print my_details
<__main__.Details instance at 0x10e2e77e8>
>>> 
>>> print my_details.name
Rishikesh
>>> print my_details.age
24
>>> 
>>> my_details.show_details()
Name :  Rishikesh
Age  :  24
>>> 
>>> person1 = Details("",34)
>>> person1.name
''
>>> person1.age
34
>>> person1.show_details
<bound method Details.show_details of <__main__.Details instance at 0x10e2e7758>>
>>> 
>>> person1.show_details()
Name :  _
Age  :  34
>>>
>>> person2 = Details("Rob Pike",0)
>>> person2.name
'Rob Pike'
>>> 
>>> person2.age
0
>>> 
>>> person2.show_details()
Name :  Rob Pike
Age  :  _
>>> 
>>> person3 = Details("Rob Pike",-45)
>>> 
>>> person3.name
'Rob Pike'
>>> 
>>> person3.age
-45
>>> 
>>> person3.show_details()
Name :  Rob Pike
Age can't be -ve
>>>
>>> person3.__dict__
{'age': -45, 'name': 'Rob Pike'}
>>>
>>> person3.__dict__.keys()
['age', 'name']
>>>
>>> person3.__dict__.values()
[-45, 'Rob Pike']
>>>

Solution 17 - Python

attributes_list = [attribute for attribute in dir(obj) if attribute[0].islower()]

Solution 18 - Python

__attrs__ gives the list of attributes of an instance.

>>> import requests
>>> r=requests.get('http://www.google.com')
>>> r.__attrs__
['_content', 'status_code', 'headers', 'url', 'history', 'encoding', 'reason', 'cookies', 'elapsed', 'request']
>>> r.url
'http://www.google.com/'
>>>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMadSc13ntistView Question on Stackoverflow
Solution 1 - PythonRoger PateView Answer on Stackoverflow
Solution 2 - PythonHtechnoView Answer on Stackoverflow
Solution 3 - PythongrepitView Answer on Stackoverflow
Solution 4 - PythonrohithprView Answer on Stackoverflow
Solution 5 - PythonuserView Answer on Stackoverflow
Solution 6 - PythonSilentGhostView Answer on Stackoverflow
Solution 7 - PythonJason AngelView Answer on Stackoverflow
Solution 8 - PythonMichael EkokaView Answer on Stackoverflow
Solution 9 - PythonJeff SilvermanView Answer on Stackoverflow
Solution 10 - PythonMike GrahamView Answer on Stackoverflow
Solution 11 - PythonLokesh kumarView Answer on Stackoverflow
Solution 12 - PythonGershom MaesView Answer on Stackoverflow
Solution 13 - PythonBlessedView Answer on Stackoverflow
Solution 14 - PythonShmulikAView Answer on Stackoverflow
Solution 15 - Pythonc zView Answer on Stackoverflow
Solution 16 - PythonhygullView Answer on Stackoverflow
Solution 17 - Pythonshammerw0wView Answer on Stackoverflow
Solution 18 - PythonVivekView Answer on Stackoverflow