The dir() built-in function returns an alphabetically sorted list of valid attribute and method names for a given object or the current local scope.
Introspection & Attribute Discovery: Without arguments, dir() returns all identifiers defined in the current local scope. When passed an object, it inspects its __dir__() hook or underlying symbol tables to discover attributes, methods, and dunders. To retrieve actual attribute values in dictionary format, see vars(). For programmatic attribute retrieval, see getattr() and hasattr(), or consult formatted documentation with help().
The dir() function accepts up to one optional parameter and always returns a sorted list of strings:
# Formal syntax of built-in dir()
attribute_list = dir([object])
| Parameter | Type | Default | Description & Operational Rule |
|---|---|---|---|
object |
Any |
Optional | Target module, class, instance, or built-in whose attributes will be inspected. |
| Return | list[str] |
N/A | An alphabetically sorted list of attribute and method names. |
| No Argument | Current Scope | N/A | Returns names bound within the caller's current local symbol table. |
Calling dir() without arguments lists all variables, imported modules, and functions bound in the current frame:
# 1. Inspecting current local scope without arguments
user_name = "Alex"
active_sessions = 12
# Calling dir() without arguments returns all names in the current scope
scope_names = dir()
print("User variables discovered in scope:")
print([name for name in scope_names if not name.startswith("_")])Terminal Output:
User variables discovered in scope:
['active_sessions', 'scope_names', 'user_name']
Passing a module or class identifier reveals all public members and internal special methods:
# 2. Inspecting module and data structure attributes
import math
# Discovering functions and constants in the math module
math_symbols = dir(math)
print("Total symbols in math: ", len(math_symbols))
print("Sample trigonometric items:", [s for s in math_symbols if "sin" in s or "cos" in s])
# Inspecting built-in list methods
list_methods = [m for m in dir(list) if not m.startswith("_")]
print("Public list methods: ", list_methods)Terminal Output:
Total symbols in math: 55
Sample trigonometric items: ['acos', 'acosh', 'asin', 'asinh', 'cos', 'cosh', 'sin', 'sinh']
Public list methods: ['append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
When dir(object) is called, Python checks if the object implements a custom __dir__() method. Defining __dir__() allows classes to expose a curated attribute list:
# 3. Customizing attribute discovery with __dir__()
class SecureVault:
def __init__(self, owner, secret_key):
self.owner = owner
self._secret_key = secret_key
def unlock(self):
return "Vault open"
def __dir__(self):
# Explicitly control which attributes appear in dir() inspection
return ["owner", "unlock"]
vault = SecureVault("plus2net", "classified_99")
print("Controlled dir() output:", dir(vault))Terminal Output:
Controlled dir() output: ['owner', 'unlock']
To inspect only user-accessible methods, filter out attributes starting with underscores:
# 4. Filtering public methods vs. special dunders
class AccountService:
service_id = "SVC-01"
def deposit(self, amount):
pass
def withdraw(self, amount):
pass
# Filter only public callable methods
public_methods = [
attr for attr in dir(AccountService)
if not attr.startswith("_") and callable(getattr(AccountService, attr))
]
print("Public callable methods:", public_methods)Terminal Output:
Public callable methods: ['deposit', 'withdraw']
Choosing the appropriate introspection tool:
| Feature | dir() |
vars() |
help() |
|---|---|---|---|
| Return Type | list[str] (sorted names) |
dict (name → value mapping) |
None (prints text manual) |
| Values Included | No (names only) | Yes (maps keys to bound values) | Yes (signatures & descriptions) |
| Inherited Attributes | Yes (traverses inheritance tree) | No (only instance/class __dict__) |
Yes (full class hierarchy) |
Discover and invoke plugin event handler methods dynamically at runtime:
# 5. Production Recipe: Dynamic Plugin Hook Runner
class AnalyticsPlugin:
def hook_on_login(self, user):
return f"Analytics: {user} logged in"
def hook_on_logout(self, user):
return f"Analytics: {user} logged out"
def internal_utility(self):
pass
def trigger_hooks(plugin_instance, hook_event, *args):
"""Discovers and executes methods matching the hook pattern dynamically."""
target_name = f"hook_{hook_event}"
available_methods = dir(plugin_instance)
if target_name in available_methods:
method = getattr(plugin_instance, target_name)
if callable(method):
return method(*args)
return None
plugin = AnalyticsPlugin()
print(trigger_hooks(plugin, "on_login", "David"))
print(trigger_hooks(plugin, "on_logout", "David"))Terminal Output:
Analytics: David logged in
Analytics: David logged out
Attributes created dynamically through __getattr__() or dynamic property getters do not appear in dir() unless the class explicitly implements __dir__():
# 6. Common traps: dynamic attributes not appearing in dir()
class DynamicBag:
def __getattr__(self, name):
# Attribute is dynamically created on access
if name.startswith("dynamic_"):
return "Generated value"
raise AttributeError(name)
bag = DynamicBag()
print("Direct dynamic access: ", bag.dynamic_field)
print("Field in dir(bag)? ", "dynamic_field" in dir(bag))Terminal Output:
Direct dynamic access: Generated value
Field in dir(bag)? False
Practice object introspection, attribute filtering, and custom __dir__() overrides in our interactive companion Jupyter Notebook:
Explore interactive code cells, inspect standard library modules, implement custom __dir__() methods, and run self-validating assertions.
Run these unit checks directly in Python or your local environment to verify dir() mechanics:
# 7. Self-verifying unit test suite for dir()
import math
# Test 1: dir() returns a list
assert isinstance(dir(), list), "dir() must return a list"
# Test 2: Standard methods on list
list_attrs = dir([])
assert "append" in list_attrs and "extend" in list_attrs
# Test 3: Module introspection
assert "pi" in dir(math) and "sqrt" in dir(math)
# Test 4: Custom __dir__() override
class CustomDiscover:
def __dir__(self): return ["alpha", "beta"]
assert dir(CustomDiscover()) == ["alpha", "beta"]
# Test 5: Sorted order invariant
attrs = dir(str)
assert attrs == sorted(attrs), "dir() results must be alphabetically sorted"
print("All dir() unit assertions successfully verified!")Terminal Output:
All dir() unit assertions successfully verified!
Yes. Python guarantees that dir() returns an alphabetically sorted list of string attribute names.
Yes. Unlike vars() or __dict__, dir() inspects the object, its class, and all base classes recursively.
Use a list comprehension: [attr for attr in dir(obj) if not attr.startswith('__')].
To expose dynamically generated attributes (such as proxy or delegate properties) to interactive shells like IPython and auto-completers.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.