vars() in Python 2026: Accessing Object Namespace + Modern Introspection Patterns str() in Python 2026: String Conversion + Modern Formatting & Best Practices type() in Python 2026: Dynamic Type Inspection & Object Creation + Modern Patterns super() in Python 2026: Method Resolution & Modern Inheritance Patterns tuple() in Python 2026: Immutable Sequences + Modern Patterns & Best Practices staticmethod() in Python 2026: Static Methods, Utility Functions & Modern Best Practices sum() in Python 2026: Summing Iterables + Modern Numeric Patterns & Best Practices sorted() in Python 2026: Sorting Iterables + Modern Patterns & Best Practices slice() in Python 2026: Creating Slice Objects + Modern Patterns & Best Practices setattr() in Python 2026: Dynamic Attribute Setting + Modern Patterns & Safety set() in Python 2026: Mutable Sets Creation + Modern Patterns & Best Practices round() in Python 2026: Rounding Numbers + Modern Precision & Use Cases reversed() in Python 2026: Reverse Iteration + Modern Patterns & Best Practices repr() in Python 2026: Official String Representation + Modern Debugging & Serialization Use Cases pow() in Python 2026: Power & Modular Exponentiation + Modern Use Cases & Best Practices property() in Python 2026: Properties, Getters/Setters & Modern Patterns ord() in Python 2026: Unicode Code Point from Character + Modern Use Cases & Best Practices open() in Python 2026: File Handling + Modern I/O Patterns & Best Practices range() in Python 2026: Efficient Sequence Generation + Modern Patterns & Best Practices print() in Python 2026: Output Formatting + Modern CLI & Debugging Patterns View all in this category →

dir() in Python 2026: Introspection & Object Attribute Listing + Modern Use Cases

Built In Function Mar 06, 2023

dir() in Python 2026: Introspection & Object Attribute Listing + Modern Use Cases

The built-in dir() function returns a sorted list of valid attribute names for an object — the most basic and powerful introspection tool in Python. In 2026 it remains indispensable for debugging, REPL exploration, dynamic attribute access, metaprogramming, testing, and IDE-like functionality in scripts or notebooks.

With Python 3.12–3.14+ improving attribute lookup performance, enhancing free-threading safety for introspection, and better support for type annotations on dynamic objects, dir() is more reliable and useful than ever in concurrent code, plugin systems, and AI-assisted development. This March 23, 2026 update explains how dir() behaves today, real-world patterns, filtering techniques, and best practices for clean, maintainable introspection in modern Python.

TL;DR — Key Takeaways 2026

  • dir(obj) → returns list[str] of attribute/method names (sorted)
  • dir() with no argument → lists current scope (locals + globals)
  • 2026 best practice: Use dir() for debugging & exploration; filter results for production code
  • Main use cases: interactive debugging, dynamic dispatch, plugin inspection, testing assertions
  • Performance: Fast — C-level, but avoid in hot loops due to list creation

1. Basic Usage — Listing Attributes


class Person:
    def __init__(self, name):
        self.name = name
    def greet(self):
        return f"Hello, {self.name}"

p = Person("Alice")
print(dir(p))
# ['__class__',
#  '__delattr__',
#  '__dict__',
#  ...,
#  'greet',
#  'name']

print(dir())  # current scope attributes

2. Real-World Patterns in 2026

Debugging & REPL Exploration


def inspect(obj):
    print(f"Attributes of {type(obj).__name__}:")
    for attr in dir(obj):
        if not attr.startswith("_"):
            print(f"  {attr}")

inspect(p)
# Attributes of Person:
#   greet
#   name

Dynamic Method Dispatch / Plugin Inspection


def find_actions(obj):
    return [name for name in dir(obj) if callable(getattr(obj, name)) and not name.startswith("_")]

print(find_actions(p))  # ['greet']

Testing / Assertion Helpers


def assert_has_attr(obj, attr_name: str):
    if attr_name not in dir(obj):
        raise AssertionError(f"Missing attribute: {attr_name}")

assert_has_attr(p, "greet")

3. dir() vs Alternatives – Comparison 2026

Approach Output Dynamic? Best For
dir(obj)sorted list of strYesGeneral introspection
obj.__dict__.keys()dict_keys of instance attrsYesOnly instance attributes
vars(obj)dict of instance attrsYesReadable dict view (not all objects)
inspect.getmembers(obj)list of (name, value) tuplesYesDetailed inspection (value included)

4. Best Practices & Performance in 2026

  • Filter out dunders — [a for a in dir(obj) if not a.startswith("_")]
  • Type hints 2026:
    
    from typing import Any, Iterable
    
    def public_attrs(obj: Any) -> list[str]:
        return [a for a in dir(obj) if not a.startswith("_")]
    
  • Performance: dir() is fast but creates a list — avoid in very hot loops
  • Free-threading (3.14+): Safe for reads; use locks if modifying attributes concurrently
  • Avoid: dir() on very large objects (many attributes) — can be slow to list

Worked Example: dir() vs vars() vs inspect

dir(obj) lists names you can access on an object, including inherited ones and methods from the class, sorted alphabetically. vars(obj) returns only the instance's own __dict__, the data actually stored on it. inspect.getmembers() returns name/value pairs and can filter by kind. A class can also customise dir() by defining __dir__, so treat its output as a helpful listing, not a guaranteed contract.

import inspect

class Base:
    kind = "base"
    def hello(self):
        return "hi"

class Item(Base):
    def __init__(self, sku, price):
        self.sku = sku
        self.price = price
    def total(self, qty):
        return self.price * qty

it = Item("A1", 9.5)
public = [n for n in dir(it) if not n.startswith("_")]
print(public)                      # ['hello', 'kind', 'price', 'sku', 'total']
print(vars(it))                    # {'sku': 'A1', 'price': 9.5}

methods = [name for name, _ in inspect.getmembers(it, inspect.ismethod)]
print(methods)                     # ['__init__', 'hello', 'total']
print("kind" in vars(it), hasattr(it, "kind"))   # False True

The last line shows the difference clearly: kind is reachable on the instance but not stored on it.

Common Mistakes

  • Using name in dir(obj) as an existence test: hasattr() is faster and respects __getattr__
  • Expecting dir() to show only data: it mixes methods and attributes
  • Relying on dir() output in production logic: it is designed for interactive use

Quick Summary

  • dir() = everything accessible, sorted
  • vars() = only the object's own attributes
  • inspect.getmembers() = filtered name/value pairs

Conclusion — dir() in 2026: Introspection Essential

dir() is the quickest way to discover what an object can do — perfect for debugging, REPL exploration, dynamic code, and testing. In 2026, use it with filtering, type hints, and caution in performance-critical paths. It’s simple, fast, and one of Python’s most powerful introspection helpers — essential for understanding any unknown object.

Next steps:

  • Run dir() on your next unfamiliar object or module

Related Tutorials

Share:
Last updated: March 2023
Built-in Functions in Python 2026 str() in Python 2026: String Conversion + Modern Formatting & Best Practices memoryview with JAX in Python 2026: Zero-Copy NumPy → JAX Array Interop + Efficient ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + GPU Pinning & ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + ML Examples memoryview with NumPy & PyTorch in Python 2026: Zero-Copy Views, Efficient Slicing & ML Interop Examples memoryview with NumPy in Python 2026: Zero-Copy Views, Efficient Slicing & Real ML Examples memoryview() in Python 2026: Zero-Copy Magic for Large Binary Data + Real Examples import() in Python 2026: How It Works, Security Risks & Modern Alternatives (importlib) zip() in Python 2026: How to Use It, strict=True Behavior & Real-World Examples vars() in Python 2026: Accessing Object Namespace + Modern Introspection Patterns type() in Python 2026: Dynamic Type Inspection & Object Creation + Modern Patterns tuple() in Python 2026: Immutable Sequences + Modern Patterns & Best Practices super() in Python 2026: Method Resolution & Modern Inheritance Patterns sum() in Python 2026: Summing Iterables + Modern Numeric Patterns & Best Practices staticmethod() in Python 2026: Static Methods, Utility Functions & Modern Best Practices sorted() in Python 2026: Sorting Iterables + Modern Patterns & Best Practices slice() in Python 2026: Creating Slice Objects + Modern Patterns & Best Practices setattr() in Python 2026: Dynamic Attribute Setting + Modern Patterns & Safety set() in Python 2026: Mutable Sets Creation + Modern Patterns & Best Practices