Python
object-attributes
programming
Python-tips
coding

Get all object attributes in Python?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Getting all attributes of an object in Python is useful for debugging, serialization, and dynamic inspection. The primary tools are dir(), which lists all attribute names including inherited and special ones, and vars(), which returns the instance's __dict__ containing only its own attributes. For more detailed inspection, the inspect module provides functions to distinguish between methods, properties, and data attributes. Understanding these tools helps you explore unfamiliar objects and build dynamic, reflection-based code.

Using dir()

dir() returns a sorted list of all attribute names for an object, including inherited attributes and special (dunder) methods:

python
1class Animal:
2    species = "Unknown"
3
4    def __init__(self, name, age):
5        self.name = name
6        self.age = age
7
8    def speak(self):
9        return f"{self.name} makes a sound"
10
11dog = Animal("Rex", 5)
12
13print(dir(dog))
14# ['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__',
15#  '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__',
16#  '__hash__', '__init__', '__init_subclass__', ..., 'age', 'name', 'speak',
17#  'species']

To filter out dunder attributes:

python
1# Only user-defined attributes and methods
2public_attrs = [a for a in dir(dog) if not a.startswith("_")]
3print(public_attrs)
4# ['age', 'name', 'speak', 'species']

Using vars()

vars() returns the __dict__ of an object — only the instance attributes, not class attributes or methods:

python
1print(vars(dog))
2# {'name': 'Rex', 'age': 5}
3
4# Equivalent to:
5print(dog.__dict__)
6# {'name': 'Rex', 'age': 5}

Notice that species (class attribute) and speak (method) are not in vars() because they belong to the class, not the instance.

Comparing dir() and vars()

python
1class Car:
2    wheels = 4  # Class attribute
3
4    def __init__(self, make, model):
5        self.make = make    # Instance attribute
6        self.model = model  # Instance attribute
7
8    def start(self):
9        return f"{self.make} {self.model} started"
10
11car = Car("Toyota", "Camry")
12
13# dir() — everything including inherited
14dir_attrs = [a for a in dir(car) if not a.startswith("_")]
15print(dir_attrs)
16# ['make', 'model', 'start', 'wheels']
17
18# vars() — instance attributes only
19print(vars(car))
20# {'make': 'Toyota', 'model': 'Camry'}
Featuredir()vars()
Instance attributesYesYes
Class attributesYesNo
MethodsYesNo
Inherited attributesYesNo
Special methodsYesNo
ReturnsList of stringsDictionary

Using getattr() for Dynamic Access

python
1class Config:
2    def __init__(self):
3        self.debug = True
4        self.host = "localhost"
5        self.port = 8080
6
7config = Config()
8
9# Access attribute by name (string)
10value = getattr(config, "host")
11print(value)  # "localhost"
12
13# With a default for missing attributes
14value = getattr(config, "missing_attr", "default_value")
15print(value)  # "default_value"
16
17# Iterate over all instance attributes
18for attr, value in vars(config).items():
19    print(f"{attr} = {value}")
20# debug = True
21# host = localhost
22# port = 8080

Using the inspect Module

The inspect module provides detailed attribute classification:

python
1import inspect
2
3class MyClass:
4    class_var = 42
5
6    def __init__(self):
7        self.instance_var = "hello"
8
9    def method(self):
10        pass
11
12    @staticmethod
13    def static_method():
14        pass
15
16    @classmethod
17    def class_method(cls):
18        pass
19
20    @property
21    def computed(self):
22        return self.instance_var.upper()
23
24obj = MyClass()
25
26# Get all members with their types
27for name, value in inspect.getmembers(obj):
28    if not name.startswith("_"):
29        print(f"{name}: {type(value).__name__}")
30# class_method: method
31# class_var: int
32# computed: str
33# instance_var: str
34# method: method
35# static_method: function

Filtering by Type

python
1# Only methods
2methods = inspect.getmembers(obj, predicate=inspect.ismethod)
3print([name for name, _ in methods if not name.startswith("_")])
4# ['class_method', 'method']
5
6# Only data attributes (not methods or properties)
7data_attrs = {k: v for k, v in vars(obj).items()}
8print(data_attrs)
9# {'instance_var': 'hello'}

Using slots

Objects with __slots__ do not have __dict__, so vars() fails:

python
1class Point:
2    __slots__ = ("x", "y")
3
4    def __init__(self, x, y):
5        self.x = x
6        self.y = y
7
8p = Point(3, 4)
9
10# vars() fails with __slots__
11# vars(p)  # TypeError: vars() argument must have __dict__ attribute
12
13# dir() still works
14print([a for a in dir(p) if not a.startswith("_")])
15# ['x', 'y']
16
17# Access slots directly
18print(p.x, p.y)  # 3 4
19
20# Get all slot values
21for slot in p.__slots__:
22    print(f"{slot} = {getattr(p, slot)}")
23# x = 3
24# y = 4

Practical Example: Object to Dictionary

python
1def obj_to_dict(obj):
2    """Convert an object's public attributes to a dictionary."""
3    if hasattr(obj, "__dict__"):
4        return {k: v for k, v in vars(obj).items() if not k.startswith("_")}
5    elif hasattr(obj, "__slots__"):
6        return {s: getattr(obj, s) for s in obj.__slots__
7                if hasattr(obj, s) and not s.startswith("_")}
8    return {}
9
10class User:
11    def __init__(self, name, email):
12        self.name = name
13        self.email = email
14        self._internal = "hidden"
15
16user = User("Alice", "[email protected]")
17print(obj_to_dict(user))
18# {'name': 'Alice', 'email': '[email protected]'}

Common Pitfalls

  • Assuming vars() shows all attributes: vars() only returns instance attributes stored in __dict__. Class attributes, methods, properties, and __slots__ attributes are not included. Use dir() for a complete list.
  • Using vars() on objects with __slots__: Objects with __slots__ do not have __dict__, so vars() raises TypeError. Check with hasattr(obj, '__dict__') first, or use dir() and getattr().
  • Modifying __dict__ directly: While obj.__dict__["new_attr"] = value works, it bypasses descriptors, properties, and __setattr__. Use setattr(obj, "new_attr", value) for safe attribute setting.
  • Confusing class attributes with instance attributes: dir() shows both, vars() shows only instance attributes. If you modify a class attribute through an instance (obj.class_var = new_value), it creates an instance attribute that shadows the class one.
  • Not filtering dunder attributes: dir() includes dozens of special methods (__init__, __repr__, __eq__, etc.). Filter with [a for a in dir(obj) if not a.startswith("_")] to see only user-defined attributes.

Summary

  • dir(obj) lists all attribute names including inherited and special attributes
  • vars(obj) returns __dict__ with instance attributes only (fails on __slots__ objects)
  • getattr(obj, name, default) accesses attributes dynamically by name
  • inspect.getmembers(obj) provides detailed classification of methods, properties, and data
  • Filter dir() results with not a.startswith("_") to see only public, user-defined attributes

Course illustration
Course illustration

All Rights Reserved.