π 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 :