- Published on
The Python `dir()` Function
Table of Contents
dir()
Function
the In Python, the dir()
function is a built-in function that returns a list of names in the current local scope or the names of an object's attributes. Here's the general syntax:
dir([object])
If object
is not provided, dir()
returns the names in the current local scope. If an object is passed as an argument, dir()
returns the names of the object's attributes and methods.
Here's an example of using the dir()
function:
# Example 1: Names in current local scope
print(dir())
# Example 2: Names of an object's attributes
my_list = [1, 2, 3]
print(dir(my_list))
In the first example, dir()
is called without any arguments, so it returns the names in the current local scope. It will include the names of variables, functions, classes, and other objects defined in the current scope.
In the second example, dir(my_list)
returns the names of attributes and methods of the my_list
object. These may include methods like append()
, remove()
, or attributes like count
, index
, and so on, that are available for list objects.
Note that dir()
returns a list of strings, and it may include some built-in names or names defined by imported modules, depending on the context in which it is called.
Practical Use Cases
1. Exploring New Libraries
When working with unfamiliar libraries or modules, dir()
is invaluable for discovery:
import pandas as pd
# Discover available methods and attributes
print(dir(pd))
# Explore DataFrame methods
df = pd.DataFrame({'A': [1, 2, 3]})
methods = [method for method in dir(df) if not method.startswith('_')]
print(methods)
2. Debugging and Introspection
Use dir()
during debugging to understand what's available on an object:
class DataProcessor:
def __init__(self):
self.data = []
self.processed = False
def process(self):
self.processed = True
processor = DataProcessor()
print(dir(processor))
# Output includes: 'data', 'process', 'processed', and inherited methods
3. Interactive Development
In interactive Python sessions (REPL or Jupyter), dir()
helps you quickly recall method names:
# Quick check of string methods
text = "hello"
string_methods = [m for m in dir(text) if not m.startswith('_')]
print(string_methods)
# ['capitalize', 'casefold', 'center', 'count', 'encode', ...]
Advanced Usage
Filtering Results
Filter dir()
output to show only public attributes:
def get_public_attributes(obj):
"""Get all public attributes and methods of an object."""
return [attr for attr in dir(obj) if not attr.startswith('_')]
my_list = [1, 2, 3]
public_attrs = get_public_attributes(my_list)
print(public_attrs)
# ['append', 'clear', 'copy', 'count', 'extend', 'index', ...]
type()
and help()
Combining with import numpy as np
# Discover what numpy offers
print(f"NumPy version: {np.__version__}")
print(f"NumPy type: {type(np)}")
# Get specific function info
functions = [name for name in dir(np) if callable(getattr(np, name))]
print(f"NumPy has {len(functions)} callable functions")
# Use help() for detailed info on specific items
help(np.array)
Inspecting Custom Classes
class Vehicle:
wheels = 4
def __init__(self, brand):
self.brand = brand
self._private = "private data"
def drive(self):
return f"{self.brand} is driving"
car = Vehicle("Toyota")
print(dir(car))
# Separate class attributes from instance attributes
class_attrs = dir(Vehicle)
instance_attrs = dir(car)
unique_to_instance = set(instance_attrs) - set(class_attrs)
print(f"Instance-specific attributes: {unique_to_instance}")
Comparison with Related Functions
dir()
vs vars()
class Example:
class_var = "I'm a class variable"
def __init__(self):
self.instance_var = "I'm an instance variable"
obj = Example()
# dir() shows all attributes including inherited and magic methods
print("dir():", len(dir(obj))) # ~35+ items
# vars() shows only instance dictionary
print("vars():", vars(obj)) # {'instance_var': "I'm an instance variable"}
dir()
vs help()
# dir() - Quick list of what's available
print(dir(dict))
# help() - Detailed documentation
help(dict.keys) # Shows full docstring and usage
dir()
vs type()
value = 42
# type() tells you what it is
print(type(value)) # <class 'int'>
# dir() tells you what it can do
print(dir(value)) # ['__abs__', '__add__', 'bit_length', ...]
Common Patterns and Best Practices
1. Autocomplete Helper
def show_methods(obj, pattern=""):
"""Show methods matching a pattern."""
methods = [m for m in dir(obj) if pattern.lower() in m.lower()]
return methods
# Find all methods containing 'append'
my_list = []
print(show_methods(my_list, "append")) # ['append']
# Find all string formatting methods
print(show_methods("", "format")) # ['format', 'format_map']
2. Documenting Your Classes
class APIClient:
"""Example API client with various methods."""
def get(self): pass
def post(self): pass
def delete(self): pass
@staticmethod
def available_methods():
"""Return list of available API methods."""
return [m for m in dir(APIClient)
if not m.startswith('_') and callable(getattr(APIClient, m))]
print(APIClient.available_methods())
3. Dynamic Attribute Access
class Config:
debug = True
timeout = 30
retries = 3
config = Config()
# List all configuration options
config_options = [attr for attr in dir(config)
if not attr.startswith('_') and not callable(getattr(config, attr))]
print("Configuration options:")
for option in config_options:
value = getattr(config, option)
print(f" {option}: {value}")
Performance Considerations
The dir()
function is relatively lightweight, but keep in mind:
import timeit
# Calling dir() repeatedly
setup = "obj = list(range(100))"
# Measure performance
time = timeit.timeit('dir(obj)', setup=setup, number=10000)
print(f"Time for 10,000 calls: {time:.4f} seconds")
# Tip: Cache results if calling repeatedly in loops
cached_methods = dir([])
# Use cached_methods instead of calling dir() again
Troubleshooting Common Issues
Issue 1: Too Much Output
# Problem: dir() returns too many items including magic methods
obj = "hello"
print(len(dir(obj))) # 78 items!
# Solution: Filter out magic methods
public_only = [attr for attr in dir(obj) if not attr.startswith('_')]
print(len(public_only)) # 44 items
Issue 2: Understanding Inherited Attributes
class Parent:
parent_method = "from parent"
class Child(Parent):
child_method = "from child"
child = Child()
# All attributes including inherited
all_attrs = dir(child)
# Only child-specific
child_specific = set(dir(child)) - set(dir(Parent))
print(f"Child-specific: {child_specific}")
Issue 3: Dynamic Attributes
class DynamicClass:
def __getattr__(self, name):
return f"Dynamic: {name}"
obj = DynamicClass()
# dir() won't show dynamically created attributes
print(dir(obj)) # Doesn't show dynamic attributes
# They're still accessible
print(obj.anything) # "Dynamic: anything"
dir()
When NOT to Use While dir()
is useful, it's not always the right tool:
- For Documentation: Use
help()
instead for detailed information - For Type Checking: Use
isinstance()
ortype()
- For Attribute Checking: Use
hasattr()
for specific attribute existence - For Production Code: Don't rely on
dir()
for critical logic; use explicit attribute access
# Bad: Using dir() to check for attribute
if 'append' in dir(my_list):
my_list.append(value)
# Good: Use hasattr() instead
if hasattr(my_list, 'append'):
my_list.append(value)
# Better: Just use try/except or duck typing
try:
my_list.append(value)
except AttributeError:
print("Object doesn't support append")
Conclusion
The dir()
function is an essential tool for Python developers, especially when:
- Learning new libraries and APIs
- Debugging unfamiliar code
- Working interactively in REPL or Jupyter notebooks
- Exploring object capabilities dynamically
Combined with help()
, type()
, and vars()
, dir()
forms part of Python's powerful introspection toolkit that makes the language approachable and explorable.
Related Topics
- Python Cheat Sheet - Quick reference for Python syntax and functions
- Top Python Libraries - Explore essential Python libraries
Related Articles
Python Cheat Sheet
Awesome Python frameworks. A curated list of awesome Python frameworks, libraries, software and resources.
PyTorch for Python
PyTorch is a popular open-source library primarily used for deep learning applications but also offers versatility in general machine learning areas.
Awesome Python frameworks
Awesome Python frameworks. A curated list of awesome Python frameworks, libraries, software and resources.