Developer-Facing Evaluations via repr

🏷️ Object-Oriented Programming (OOP) Basics / Special Dunder Methods

🧠 Context Introduction

When you're building Python classes, you'll often need to inspect objects during development or debugging. The default string representation of an object (like <main.MyObject object at 0x7f8c1a2b3c4d>) isn't very helpful. This is where the repr method comes in. It gives you a developer-friendly, unambiguous representation of your objectβ€”perfect for logging, debugging, and interactive sessions.


🎯 What is repr?

The repr method is a special dunder method that defines how your object appears when:

  • You print the object directly
  • You inspect it in a Python REPL (interactive shell)
  • You use it in debugging tools or loggers

The goal of repr is to return a string that, ideally, could be used to recreate the object. It's meant for other developers, not end users.


βš™οΈ Basic Syntax and Behavior

  • repr is defined inside your class as def repr(self):
  • It must return a string
  • It takes only self as an argument
  • It's automatically called when you use repr() on an object or when the object is displayed in the REPL

Example of default behavior without repr: - Creating a simple class like class Server: with def init(self, name, ip): and self.name = name and self.ip = ip - Instantiating with s = Server("web01", "10.0.0.1") - Typing s in the REPL shows something like <main.Server object at 0x7f8c1a2b3c4d> β€” not useful at all


πŸ› οΈ Implementing repr

To make your objects more developer-friendly, you define repr to return a meaningful string. The convention is to return a string that looks like a valid Python expression to recreate the object.

Example implementation: - def repr(self): inside your class - return f"Server('{self.name}', '{self.ip}')" - Now typing s in the REPL shows Server('web01', '10.0.0.1')

This tells you exactly what the object contains and how to recreate it.


πŸ“Š repr vs str: Key Differences

Feature repr str
Primary Audience Developers End users
Goal Unambiguous, detailed representation Readable, user-friendly output
Called by repr(), REPL display, debugging print(), str(), f-strings
Fallback behavior If str is missing, repr is used If repr is missing, default object representation is used
Convention Should look like a valid Python expression Can be any readable string

πŸ•΅οΈ When to Use repr

Use repr when you need to:

  • Debug your code and inspect object state
  • Log object details in error messages or logs
  • Work in interactive Python sessions (REPL, Jupyter notebooks)
  • Create meaningful test assertions
  • Document what an object contains for other developers

Best practice: Always define repr for your classes, even if you also define str. This ensures developers always get useful information.


πŸ’‘ Practical Examples for Engineers

Example 1: Simple Server Class - Class Server with attributes name, ip, status - repr returns f"Server(name='{self.name}', ip='{self.ip}', status='{self.status}')" - When debugging, you see Server(name='web01', ip='10.0.0.1', status='active') instead of a memory address

Example 2: Configuration Object - Class Config with attributes host, port, timeout - repr returns f"Config(host='{self.host}', port={self.port}, timeout={self.timeout})" - This makes it easy to copy-paste the output back into code for testing

Example 3: Database Connection - Class DatabaseConnection with attributes host, database, user - repr returns f"DatabaseConnection(host='{self.host}', db='{self.database}', user='{self.user}')" - Helps quickly identify which connection you're working with in logs


πŸ” Common Pitfalls to Avoid

  • Returning non-string types: repr must return a string, not a number or list
  • Forgetting to include key attributes: Your representation should show the most important state
  • Making it too verbose: Include enough to identify the object, but don't dump every internal detail
  • Using it for user-facing output: That's what str is for
  • Not handling edge cases: If attributes can be None or empty, make sure your representation still works

βœ… Summary Checklist

  • [ ] Define repr in every class you create
  • [ ] Return a string that looks like a valid Python expression
  • [ ] Include the most important attributes for identification
  • [ ] Use f-strings for clean, readable formatting
  • [ ] Remember that repr is for developers, not end users
  • [ ] Test your repr output in the REPL to ensure it's helpful

πŸš€ Final Thoughts

The repr method is one of the most valuable tools for making your Python code more maintainable and debuggable. By providing clear, unambiguous representations of your objects, you save yourself and your team hours of debugging time. Make it a habit to always implement reprβ€”your future self (and your colleagues) will thank you.


The __repr__ method defines how an object appears when engineers inspect it in the console or debugger, returning a string that ideally recreates the object.


πŸ›  Example 1: Default __repr__ behavior

Shows what Python outputs when no __repr__ is defined β€” a generic memory address.

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower

motor = Engine(300)
print(motor)

πŸ“€ Output: <__main__.Engine object at 0x7f8b1c0b4a90>


πŸ”§ Example 2: Basic __repr__ returning a simple string

Demonstrates overriding __repr__ to return a custom string instead of the default.

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower

    def __repr__(self):
        return f"Engine with {self.horsepower} HP"

motor = Engine(300)
print(motor)

πŸ“€ Output: Engine with 300 HP


βš™οΈ Example 3: __repr__ that shows object creation code

Shows the standard convention β€” __repr__ returns a string that could recreate the object.

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower

    def __repr__(self):
        return f"Engine({self.horsepower})"

motor = Engine(300)
print(repr(motor))

πŸ“€ Output: Engine(300)


πŸ”© Example 4: __repr__ with multiple attributes

Demonstrates how to include all relevant fields so engineers see the full object state.

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year

    def __repr__(self):
        return f"Car('{self.make}', '{self.model}', {self.year})"

my_car = Car("Toyota", "Camry", 2022)
print(repr(my_car))

πŸ“€ Output: Car('Toyota', 'Camry', 2022)


πŸ›ž Example 5: Practical use β€” debugging a list of objects

Shows how __repr__ helps engineers inspect collections of objects at a glance.

class Sensor:
    def __init__(self, name, value):
        self.name = name
        self.value = value

    def __repr__(self):
        return f"Sensor('{self.name}', {self.value})"

sensors = [
    Sensor("temperature", 72.5),
    Sensor("pressure", 101.3),
    Sensor("humidity", 45.0)
]

print(sensors)

πŸ“€ Output: [Sensor('temperature', 72.5), Sensor('pressure', 101.3), Sensor('humidity', 45.0)]


Comparison Table

Aspect Without __repr__ With __repr__
Console output <__main__.Engine object at 0x...> Engine(300)
Debugging clarity Low β€” memory address only High β€” shows object state
Code recreation Not possible Possible via returned string
Engineer usefulness Minimal Essential for inspection

🧠 Context Introduction

When you're building Python classes, you'll often need to inspect objects during development or debugging. The default string representation of an object (like <main.MyObject object at 0x7f8c1a2b3c4d>) isn't very helpful. This is where the repr method comes in. It gives you a developer-friendly, unambiguous representation of your objectβ€”perfect for logging, debugging, and interactive sessions.


🎯 What is repr?

The repr method is a special dunder method that defines how your object appears when:

  • You print the object directly
  • You inspect it in a Python REPL (interactive shell)
  • You use it in debugging tools or loggers

The goal of repr is to return a string that, ideally, could be used to recreate the object. It's meant for other developers, not end users.


βš™οΈ Basic Syntax and Behavior

  • repr is defined inside your class as def repr(self):
  • It must return a string
  • It takes only self as an argument
  • It's automatically called when you use repr() on an object or when the object is displayed in the REPL

Example of default behavior without repr: - Creating a simple class like class Server: with def init(self, name, ip): and self.name = name and self.ip = ip - Instantiating with s = Server("web01", "10.0.0.1") - Typing s in the REPL shows something like <main.Server object at 0x7f8c1a2b3c4d> β€” not useful at all


πŸ› οΈ Implementing repr

To make your objects more developer-friendly, you define repr to return a meaningful string. The convention is to return a string that looks like a valid Python expression to recreate the object.

Example implementation: - def repr(self): inside your class - return f"Server('{self.name}', '{self.ip}')" - Now typing s in the REPL shows Server('web01', '10.0.0.1')

This tells you exactly what the object contains and how to recreate it.


πŸ“Š repr vs str: Key Differences

Feature repr str
Primary Audience Developers End users
Goal Unambiguous, detailed representation Readable, user-friendly output
Called by repr(), REPL display, debugging print(), str(), f-strings
Fallback behavior If str is missing, repr is used If repr is missing, default object representation is used
Convention Should look like a valid Python expression Can be any readable string

πŸ•΅οΈ When to Use repr

Use repr when you need to:

  • Debug your code and inspect object state
  • Log object details in error messages or logs
  • Work in interactive Python sessions (REPL, Jupyter notebooks)
  • Create meaningful test assertions
  • Document what an object contains for other developers

Best practice: Always define repr for your classes, even if you also define str. This ensures developers always get useful information.


πŸ’‘ Practical Examples for Engineers

Example 1: Simple Server Class - Class Server with attributes name, ip, status - repr returns f"Server(name='{self.name}', ip='{self.ip}', status='{self.status}')" - When debugging, you see Server(name='web01', ip='10.0.0.1', status='active') instead of a memory address

Example 2: Configuration Object - Class Config with attributes host, port, timeout - repr returns f"Config(host='{self.host}', port={self.port}, timeout={self.timeout})" - This makes it easy to copy-paste the output back into code for testing

Example 3: Database Connection - Class DatabaseConnection with attributes host, database, user - repr returns f"DatabaseConnection(host='{self.host}', db='{self.database}', user='{self.user}')" - Helps quickly identify which connection you're working with in logs


πŸ” Common Pitfalls to Avoid

  • Returning non-string types: repr must return a string, not a number or list
  • Forgetting to include key attributes: Your representation should show the most important state
  • Making it too verbose: Include enough to identify the object, but don't dump every internal detail
  • Using it for user-facing output: That's what str is for
  • Not handling edge cases: If attributes can be None or empty, make sure your representation still works

βœ… Summary Checklist

  • [ ] Define repr in every class you create
  • [ ] Return a string that looks like a valid Python expression
  • [ ] Include the most important attributes for identification
  • [ ] Use f-strings for clean, readable formatting
  • [ ] Remember that repr is for developers, not end users
  • [ ] Test your repr output in the REPL to ensure it's helpful

πŸš€ Final Thoughts

The repr method is one of the most valuable tools for making your Python code more maintainable and debuggable. By providing clear, unambiguous representations of your objects, you save yourself and your team hours of debugging time. Make it a habit to always implement reprβ€”your future self (and your colleagues) will thank you.

Interactive Views

You are currently in πŸ“š All-in-One mode. Use the tabs at the top to switch to πŸ“– Theory Only or πŸ’» Code Only views.

The __repr__ method defines how an object appears when engineers inspect it in the console or debugger, returning a string that ideally recreates the object.


πŸ›  Example 1: Default __repr__ behavior

Shows what Python outputs when no __repr__ is defined β€” a generic memory address.

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower

motor = Engine(300)
print(motor)

πŸ“€ Output: <__main__.Engine object at 0x7f8b1c0b4a90>


πŸ”§ Example 2: Basic __repr__ returning a simple string

Demonstrates overriding __repr__ to return a custom string instead of the default.

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower

    def __repr__(self):
        return f"Engine with {self.horsepower} HP"

motor = Engine(300)
print(motor)

πŸ“€ Output: Engine with 300 HP


βš™οΈ Example 3: __repr__ that shows object creation code

Shows the standard convention β€” __repr__ returns a string that could recreate the object.

class Engine:
    def __init__(self, horsepower):
        self.horsepower = horsepower

    def __repr__(self):
        return f"Engine({self.horsepower})"

motor = Engine(300)
print(repr(motor))

πŸ“€ Output: Engine(300)


πŸ”© Example 4: __repr__ with multiple attributes

Demonstrates how to include all relevant fields so engineers see the full object state.

class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year

    def __repr__(self):
        return f"Car('{self.make}', '{self.model}', {self.year})"

my_car = Car("Toyota", "Camry", 2022)
print(repr(my_car))

πŸ“€ Output: Car('Toyota', 'Camry', 2022)


πŸ›ž Example 5: Practical use β€” debugging a list of objects

Shows how __repr__ helps engineers inspect collections of objects at a glance.

class Sensor:
    def __init__(self, name, value):
        self.name = name
        self.value = value

    def __repr__(self):
        return f"Sensor('{self.name}', {self.value})"

sensors = [
    Sensor("temperature", 72.5),
    Sensor("pressure", 101.3),
    Sensor("humidity", 45.0)
]

print(sensors)

πŸ“€ Output: [Sensor('temperature', 72.5), Sensor('pressure', 101.3), Sensor('humidity', 45.0)]


Comparison Table

Aspect Without __repr__ With __repr__
Console output <__main__.Engine object at 0x...> Engine(300)
Debugging clarity Low β€” memory address only High β€” shows object state
Code recreation Not possible Possible via returned string
Engineer usefulness Minimal Essential for inspection