Repr Best Practices
Comprehensive Repr Design Principles
class User:
def __init__(self, username, email, role):
self.username = username
self.email = email
self.role = role
def __repr__(self):
## Good practice: Provide key identifying information
return f"User(username='{self.username}', role='{self.role}')"
## Avoid including sensitive information like full email
user = User("labex_dev", "[email protected]", "admin")
print(repr(user))
Repr Method Design Strategies
graph TD
A[Repr Design] --> B[Conciseness]
A --> C[Readability]
A --> D[Debuggability]
A --> E[Performance]
Approach |
Recommendation |
Example |
Small Objects |
Full Representation |
Detailed attributes |
Large Collections |
Summarized Info |
Item count, type |
Nested Objects |
Controlled Depth |
Limit recursion |
Advanced Repr Techniques
Handling Complex Nested Structures
class ComplexObject:
def __init__(self, data, metadata):
self.data = data
self.metadata = metadata
def __repr__(self):
## Limit depth and prevent recursive representations
def safe_repr(obj, depth=2):
if depth == 0:
return "..."
if isinstance(obj, dict):
return "{" + ", ".join(
f"{k}: {safe_repr(v, depth-1)}"
for k, v in list(obj.items())[:3]
) + "}"
return repr(obj)
return (f"{self.__class__.__name__}("
f"data={safe_repr(self.data)}, "
f"metadata={safe_repr(self.metadata)})")
## Example usage
complex_obj = ComplexObject(
data={"nested": {"deep": "value"}},
metadata={"source": "LabEx"}
)
print(repr(complex_obj))
Common Anti-Patterns to Avoid
- Overly Verbose Representations
- Including Sensitive Data
- Recursive Representations
- Performance-Intensive Computations
Secure Repr Implementation
class SecureModel:
def __init__(self, id, sensitive_data):
self._id = id
self._sensitive_data = sensitive_data
def __repr__(self):
## Mask sensitive information
return f"{self.__class__.__name__}(id={self._id}, data=<masked>)"
## Prevents accidental exposure of sensitive details
secure_instance = SecureModel(123, "confidential_info")
print(repr(secure_instance))
Repr for Different Object Types
Collections and Complex Structures
class DataCollection:
def __init__(self, items):
self.items = items
def __repr__(self):
## Smart representation for different collection sizes
if len(self.items) == 0:
return f"{self.__class__.__name__}(empty)"
elif len(self.items) > 10:
return f"{self.__class__.__name__}(items={len(self.items)})"
else:
return f"{self.__class__.__name__}(items={self.items})"
## Demonstrates adaptive repr
small_collection = DataCollection([1, 2, 3])
large_collection = DataCollection(list(range(100)))
print(repr(small_collection))
print(repr(large_collection))
Best Practices Checklist
class OptimizedModel:
def __init__(self, data):
self.data = data
def __repr__(self):
## Lazy evaluation and caching
if not hasattr(self, '_cached_repr'):
self._cached_repr = self._generate_repr()
return self._cached_repr
def _generate_repr(self):
## Complex representation generation
return f"{self.__class__.__name__}(data_length={len(self.data)})"
By following these best practices, developers can create robust, informative, and efficient __repr__
methods that enhance code readability and debugging with LabEx's recommended approaches.