Skip to main content

How to Inspect Python Objects and Get Attributes and Methods

Python's introspection capabilities allow you to examine objects at runtime, discovering their attributes (data) and methods (functions).

This guide explains how to get a list of an object's or class's attributes and methods using dir(), vars(), __dict__, and the inspect module. We'll also cover filtering the results to get exactly what you need.

Getting Attributes with __dict__ and vars() (Instance Attributes)

Both __dict__ and vars() provide access to an object's instance attributes (not class attributes or methods) as a dictionary:

class Person():
cls_id = 'employee' # Class attribute

def __init__(self, first, last, age):
self.first = first # Instance attributes
self.last = last
self.age = age

tom = Person('tom', 'nolan', 25)

# Using __dict__
print(tom.__dict__)
# Output: {'first': 'tom', 'last': 'nolan', 'age': 25}

# Using vars() - equivalent to __dict__ for instances
print(vars(tom))
# Output: {'first': 'tom', 'last': 'nolan', 'age': 25}

# Get a list of attribute names only:
attributes = list(tom.__dict__.keys()) # or list(vars(tom))
print(attributes) # Output: ['first', 'last', 'age']
  • __dict__: Every object with dynamically assignable attributes has a __dict__ attribute. This is a dictionary where keys are attribute names (strings) and values are the corresponding attribute values.
  • vars(object): For class instances, vars(object) is equivalent to object.__dict__. It's slightly more general, as it can also be used with modules and classes (returning their __dict__). Use vars() for readability.
  • The difference between class attributes and instance attributes is that instance attributes are unique to the instance and can be modified on the object directly.

Getting All Attributes and Methods with dir()

The dir() function is a more comprehensive tool. It returns a list of all valid attributes (including methods) for a given object, including inherited attributes:

class Person():
def __init__(self, first, last, age):
self.first = first
self.last = last
self.age = age

tom = Person('tom', 'nolan', 25)
print(dir(tom))
# Output (long list, including):
# ['__class__', '__delattr__', ..., 'age', 'first', 'last', ...]
  • dir(tom): Returns a list of strings, representing all attributes (instance variables, methods, class variables, inherited members) accessible on the tom object. This includes the "magic" attributes/methods (starting and ending with double underscores) that are part of Python's object model.

Filtering dir() Results

The raw output of dir() is often too verbose. You usually want to filter it.

Excluding "Magic" Attributes (Double Underscore)

To exclude attributes that start and end with double underscores (dunder methods), use a list comprehension:

attributes = [attr for attr in dir(tom) if not attr.startswith('__')]
print(attributes) # Output: ['age', 'first', 'last']

Getting Only Methods

To get only the methods of an object, use callable() in your filter:

class Employee():
cls_id = 'employee'

def __init__(self, name, salary):
self.name = name
self.salary = salary

def get_name(self):
return self.name

def get_salary(self):
return self.salary

emp1 = Employee('tom', 'nolan')
methods = [method for method in dir(emp1)
if not method.startswith('__')
and callable(getattr(emp1, method))
]
print(methods) # Output: ['get_name', 'get_salary']

  • callable(getattr(emp1, attribute)): This is the key. getattr(emp1, attribute) retrieves the attribute (which might be a method, a variable, etc.). callable() then checks if that attribute is something you can call (like a function or method).
  • The @classmethod and @staticmethod are also considered callable, so they are included in the output as well.

Getting Class Methods with inspect.getmembers()

import inspect
class Employee():
def __init__(self, name, salary):
self.salary = salary
self.name = name

def get_name(self):
return self.name

def get_salary(self):
return self.salary

# Get class methods
list_of_methods = inspect.getmembers(Employee, predicate=inspect.isfunction)
print(list_of_methods)
#Output: [('__init__', <function Employee.__init__ at 0x...>), ('get_name', <function Employee.get_name at 0x...>), ('get_salary', <function Employee.get_salary at 0x...>)]

# Get object methods
tom = Employee('tomolan', 100)
list_of_methods = inspect.getmembers(tom, predicate=inspect.ismethod)
print(list_of_methods)
#[('__init__', <bound method Employee.__init__ of <__main__.Employee object at 0x...>>),
# ('get_name', <bound method Employee.get_name of <__main__.Employee object at 0x...>>),
# ('get_salary', <bound method Employee.get_salary of <__main__.Employee object at 0x...>)]
  • inspect.getmembers(Employee, predicate=inspect.isfunction): This returns a list of (name, value) tuples, where name is the name of the method and value is the method itself. The predicate=inspect.isfunction part filters the results, including only those members that are functions. If the argument is an instance of a class, use inspect.ismethod instead of inspect.isfunction.
  • This approach is generally better than filtering the result of the dir, because it returns more information, like method value and name.