Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Метод str в Python
Метод __str__ определяет, как объект преобразуется в строку. Это один из ключевых dunder методов в Python.
Основное назначение
__str__ вызывается при:
print(obj)str(obj)- форматировании строк
Пример без str
class User:
def __init__(self, name, email):
self.name = name
self.email = email
user = User("Alice", "alice@example.com")
print(user) # <__main__.User object at 0x7f8b8c0d5f40>
print(str(user)) # Тоже самое — непонятно
После добавления str
class User:
def __init__(self, name, email):
self.name = name
self.email = email
def __str__(self):
return f"User({self.name}, {self.email})"
user = User("Alice", "alice@example.com")
print(user) # User(Alice, alice@example.com) — понятно!
print(str(user)) # User(Alice, alice@example.com)
Практические применения
1. Логирование
При дебаге нужно видеть человеко-читаемые сообщения:
class Order:
def __init__(self, order_id, customer, total):
self.order_id = order_id
self.customer = customer
self.total = total
def __str__(self):
return f"Order #{self.order_id} ({self.customer}) - ${self.total:.2f}"
order = Order(123, "John Doe", 99.99)
print(f"Processing: {order}") # Processing: Order #123 (John Doe) - $99.99
logger.info(f"Order created: {order}") # Хороший лог
2. Ошибки и исключения
class ValidationError(Exception):
def __init__(self, field, message):
self.field = field
self.message = message
def __str__(self):
return f"ValidationError: {self.field} - {self.message}"
try:
raise ValidationError("email", "Invalid format")
except ValidationError as e:
print(e) # ValidationError: email - Invalid format
3. Форматирование в шаблонах
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def __str__(self):
return f"{self.name} (${self.price})"
products = [Product("Laptop", 999), Product("Mouse", 25)]
for product in products:
print(f"Available: {product}") # Available: Laptop ($999)
# Available: Mouse ($25)
str vs repr
Это важное различие:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
# Для пользователя, красиво
return f"Point at ({self.x}, {self.y})"
def __repr__(self):
# Для разработчика, должен быть воспроизводимым
return f"Point({self.x}, {self.y})"
point = Point(3, 4)
print(str(point)) # Point at (3, 4) — для пользователя
print(repr(point)) # Point(3, 4) — для разработчика
print(point) # Point at (3, 4) — использует __str__
Правило:
__str__— для конечного пользователя (красиво)__repr__— для разработчика (точно и воспроизводимо)
Реальные примеры
1. ORM модель (Django/SQLAlchemy)
from sqlalchemy import Column, Integer, String
from sqlalchemy.orm import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String)
email = Column(String)
def __str__(self):
return f"{self.name} <{self.email}>"
user = session.query(User).first()
print(f"User found: {user}") # User found: Alice <alice@example.com>
2. API Response object
class APIResponse:
def __init__(self, status_code, data, error=None):
self.status_code = status_code
self.data = data
self.error = error
def __str__(self):
if self.error:
return f"APIResponse({self.status_code}) ERROR: {self.error}"
return f"APIResponse({self.status_code}) - {len(str(self.data))} bytes"
response = APIResponse(200, {"user": "Alice"})
print(response) # APIResponse(200) - 21 bytes
error_response = APIResponse(500, None, "Database connection failed")
print(error_response) # APIResponse(500) ERROR: Database connection failed
3. Логирование исключений
class DatabaseError(Exception):
def __init__(self, query, original_error):
self.query = query
self.original_error = original_error
def __str__(self):
return f"Database Error:\nQuery: {self.query}\nError: {self.original_error}"
try:
# Some DB operation
pass
except Exception as e:
raise DatabaseError("SELECT * FROM users WHERE id = ?", str(e))
Когда str очень важен
1. В production логах
Логирование без __str__ выглядит так:
# ❌ Плохо
logger.error(f"Failed to process: {order_object}")
# LOG: Failed to process: <Order object at 0x7f8b8c0d5f40>
# Вообще непонятно, что произошло!
# ✅ Хорошо
logger.error(f"Failed to process: {order_object}")
# LOG: Failed to process: Order #123 (John Doe) - $99.99
# Сразу видно, какой заказ упал
2. В UI/API responses
@app.get("/orders/{order_id}")
def get_order(order_id: int):
order = db.query(Order).get(order_id)
if not order:
# ❌ Плохо
raise HTTPException(status_code=404, detail="Not found")
# ✅ Хорошо (с __str__)
raise HTTPException(
status_code=404,
detail=f"Order {order_id} not found"
)
3. При дебаге
orders = session.query(Order).all()
print(orders) # Если нет __str__, увидим кучу <Order at 0x...>
# Если есть __str__, увидим нормальные данные
Best Practice
class Entity:
"""Базовый класс для всех сущностей"""
def __str__(self):
# Всегда реализуй для production кода
attrs = ', '.join(f"{k}={v}" for k, v in self.__dict__.items())
return f"{self.__class__.__name__}({attrs})"
def __repr__(self):
# Опционально, но хорошая практика
return self.__str__()
class User(Entity):
def __init__(self, id, name, email):
self.id = id
self.name = name
self.email = email
user = User(1, "Alice", "alice@example.com")
print(user) # User(id=1, name=Alice, email=alice@example.com)
Типичная ошибка
# ❌ Возвращаешь неправильный тип
class User:
def __str__(self):
return None # TypeError: __str__ returned non-string
# ✅ Всегда возвращай строку
class User:
def __str__(self):
return "User()"
Резюме
__str__ нужен для:
- Логирования — человеко-читаемые сообщения
- Дебага — понимание состояния объекта
- UX — хорошие сообщения об ошибках
- Maintenance — легче разобраться в коде
Это особенно важно в production коде, где логи и ошибки — твой способ понять, что произошло.