Python Reflection – Dynamic Access with getattr, dir, setattr
Introduction – Why Use Reflection?
Reflection is a powerful feature in Python that allows a program to examine and manipulate its own structure and behavior at runtime. This means:
- You can access or change attributes/methods dynamically
- You can build generic, flexible, and plugin-friendly code
- You don’t need to know the names of classes or methods ahead of time
In this guide, you’ll learn:
- What reflection is and how it works in Python
- How to use
getattr(),setattr(),hasattr(),dir(), and more - Real-world examples: dynamic APIs, serializers, testing
- Best practices and common pitfalls
What Is Reflection in Python?
Reflection in Python refers to the ability to inspect and manipulate classes, objects, methods, and modules dynamically at runtime.
Core Reflection Tools
| Function | Purpose |
|---|---|
type(obj) | Returns the type of an object |
id(obj) | Returns the unique ID (memory address) |
dir(obj) | Lists all attributes/methods of an object |
getattr() | Gets the value of an attribute dynamically |
setattr() | Sets an attribute value dynamically |
hasattr() | Checks if an object has an attribute |
delattr() | Deletes an attribute from an object |
callable() | Checks if an object is callable (e.g. function) |
Example – Reflecting on an Object
class Person:
def __init__(self):
self.name = "Alice"
def greet(self):
return f"Hello, {self.name}"
p = Person()
# Reflection in action
print(type(p)) # <class '__main__.Person'>
print(dir(p)) # Lists attributes like 'name', 'greet', '__init__', etc.
print(getattr(p, "name")) # Alice
setattr(p, "name", "Bob")
print(p.greet()) # Hello, Bob
Dynamic Method Invocation
class Math:
def add(self, a, b):
return a + b
m = Math()
method_name = "add"
if hasattr(m, method_name):
func = getattr(m, method_name)
print(func(5, 3)) # Output: 8
You don’t need to hardcode method names. Perfect for plugin systems or command routers.
Using dir() and type() for Introspection
class Demo:
def __init__(self):
self.value = 42
d = Demo()
print(dir(d)) # Shows all attributes/methods
print(type(d)) # <class '__main__.Demo'>
print(callable(d)) # False
Real-World Use Case – Object Serializer
def serialize(obj):
return {
key: getattr(obj, key)
for key in dir(obj)
if not key.startswith("_") and not callable(getattr(obj, key))
}
class Product:
def __init__(self):
self.name = "Phone"
self.price = 500
p = Product()
print(serialize(p)) # {'name': 'Phone', 'price': 500}
Reflection helps build generic, reusable utilities.
Reflection vs Introspection
| Concept | Reflection | Introspection |
|---|---|---|
| Definition | Inspect and modify object structure | Only inspect object structure |
| Example Tools | getattr(), setattr() | type(), isinstance(), dir() |
| Use Case | Dynamic invocation, plugin design | Type checking, object inspection |
Common Pitfalls
| Mistake | Fix |
|---|---|
Not checking hasattr() | Use hasattr(obj, "attr") before getattr() |
| Overusing reflection in simple cases | Use direct access when possible |
| Relying on reflection for safety-critical logic | Avoid in security-sensitive contexts |
Best Practices
| Recommended | Avoid This |
|---|---|
Use hasattr() before getattr() | Blind access without checks |
| Use reflection in dynamic systems | Using it for basic static behavior |
| Document dynamic behavior clearly | Making reflection-based code opaque |
| Combine with decorators | Skipping validation and control |
Summary – Recap & Next Steps
Reflection in Python allows you to dynamically inspect and interact with code. It’s ideal for writing flexible, generic, and reusable software components.
Key Takeaways:
- Use
getattr(),setattr(),hasattr(),dir()to work with object attributes - Great for plugin systems, serializers, APIs, test runners
- Avoid unnecessary complexity—use reflection when truly needed
Real-World Relevance:
Reflection powers ORMs (like SQLAlchemy), framework internals (like Django), and test runners (like pytest).
FAQ – Python Reflection
What is reflection in Python?
It’s the ability to examine and modify objects, classes, and functions at runtime.
How do I get the value of an attribute by name?
Use getattr(obj, 'attribute_name').
Can I check if a method exists?
Yes. Use:
if hasattr(obj, 'method_name'):
getattr(obj, 'method_name')()
What is the difference between reflection and introspection?
- Reflection allows inspection + modification
- Introspection allows only inspection
Is reflection bad practice?
Not inherently. But overusing reflection can make your code harder to debug and slower in performance-critical areas.
Share Now :
