Python Custom Str
## Customizing Object String Representation in Python with `__str__`
In Python, when you print an object or convert it to a string, the output defaults to a somewhat cryptic representation showing the object's class and its memory address (for example, `<__main__.Person object at 0x7f9b182b3fd0>`).
To make your objects more readable and informative, Python provides a special "magic" (dunder) method: `__str__`. By overriding this method within your class, you can define exactly how an object should be represented as a string.
---
## Understanding `__str__`
The `__str__` method is automatically triggered by Python in several common scenarios:
* When you pass an object to the `print()` function.
* When you explicitly convert an object using the `str()` constructor.
* When you format an object inside an f-string (e.g., `f"{my_object}"`) or use `.format()`.
### Syntax
```python
class ClassName:
def __str__(self) -> str:
# Must return a string representation of the object
return "Custom string representation"
```
> **Note:** The `__str__` method **must** return a string. Returning any other data type (like an integer or `None`) will raise a `TypeError`.
---
## Code Example: Customizing Print Output
Below is a practical example demonstrating how to implement and use the `__str__` method in a custom class.
```python
class Person:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
def __str__(self) -> str:
# Return a clean, human-readable string representation
return f"Person(name={self.name}, age={self.age})"
# Create an instance of the Person class
person = Person("Alice", 30)
# Print the object directly
print(person)
# Convert the object to a string explicitly
person_str = str(person)
print("Explicit string:", person_str)
```
### Output
```text
Person(name=Alice, age=30)
Explicit string: Person(name=Alice, age=30)
```
### Code Explanation
1. **`__init__` Method**: This is the class constructor. It initializes the object's `name` and `age` attributes when a new instance is created.
2. **`__str__` Method**: This method defines the custom string format. In this case, it returns a formatted f-string containing the instance's `name` and `age`.
3. **`print(person)`**: When we pass the `person` object to `print()`, Python automatically calls `person.__str__()` behind the scenes and prints the returned string.
---
## Key Considerations: `__str__` vs `__repr__`
When customizing string representations in Python, you will often encounter both `__str__` and `__repr__`. It is important to understand the difference:
| Method | Target Audience | Primary Purpose | Fallback Behavior |
| :--- | :--- | :--- | :--- |
| **`__str__`** | End-users / General logging | To provide a clean, highly readable, and user-friendly representation. | If not defined, Python falls back to calling `__repr__`. |
| **`__repr__`** | Developers / Debuggers | To provide an unambiguous representation of the object, ideally one that can be used to recreate the object (e.g., `eval(repr(obj))`). | If not defined, Python uses the default object memory address format. |
### Best Practice Example
For robust classes, it is recommended to implement both methods:
```python
class Point:
def __init__(self, x: int, y: int):
self.x = x
self.y = y
# User-friendly representation
def __str__(self) -> str:
return f"Point at ({self.x}, {self.y})"
# Developer-friendly representation
def __repr__(self) -> str:
return f"Point(x={self.x}, y={self.y})"
p = Point(5, 10)
print(str(p)) # Output: Point at (5, 10)
print(repr(p)) # Output: Point(x=5, y=10)
```
By implementing `__str__`, you ensure that your custom Python objects are easy to debug, log, and present to users in a clean, readable format.
YouTip