Управление представлением объектов: self и print
Основной способ: переопределение метода __str__
Наиболее эффективный способ управлять выводом объекта через print заключается в переопределении специального метода __str__. Этот метод должен возвращать строку, которая и будет отображаться при вызове print(экземпляр). Внутри метода доступны все атрибуты через self.
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
def __str__(self):
return f"'{self.title}' by {self.author}"
book = Book("1984", "George Orwell")
print(book)атрибуты класса python (атрибуты классов и объектов в python)
'1984' by George Orwell
библиотека классов python (библиотека классов в python)
Альтернативные подходы
Как получить отладочное представление объекта?
Метод __repr__ предназначен для разработчиков и должен возвращать однозначное строковое представление, часто в виде кода, который можно использовать для воссоздания объекта. Если __str__ не определён, print использует __repr__.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point({self.x}, {self.y})"
p = Point(10, 20)
print(p)метод объекта python (методы объектов в python)
Point(10, 20)
Python структура объекта (структура объекта в python)
Как вывести объект с красивым форматированием?
Внутри __str__ можно использовать f-строки, методы format или конкатенацию. F-строки - самый современный и читаемый способ прямо в методе.
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def __str__(self):
return f"Сотрудник: {self.name}, зарплата: {self.salary:.2f} руб."
e = Employee("Иван", 75000.555)
print(e)Python создание объектов (создание объектов в python)
Сотрудник: Иван, зарплата: 75000.56 руб.
Self object python (объект self в python)
Как быстро вывести все атрибуты объекта?
Использование словаря self.__dict__ внутри __str__ даёт простой способ отобразить все публичные атрибуты без явного перечисления.
class Config:
def __init__(self, host, port, debug):
self.host = host
self.port = port
self.debug = debug
def __str__(self):
return f"Config: {self.__dict__}"
cfg = Config("localhost", 8080, True)
print(cfg)Object attribute python (атрибуты объекта в python)
Config: {'host': 'localhost', 'port': 8080, 'debug': True}Python call method (вызов метода в python)
Как настраивать формат вывода с помощью format()?
Метод __format__ позволяет определить поведение строки формата для экземпляра класса. Это полезно, когда требуется разное представление в зависимости от спецификатора.
class Timed:
def __init__(self, seconds):
self.seconds = seconds
def __format__(self, spec):
if spec == "hours":
return f"{self.seconds / 3600:.2f} ч"
elif spec == "minutes":
return f"{self.seconds / 60:.1f} мин"
else:
return f"{self.seconds} сек"
t = Timed(3665)
print(format(t, "hours"))
print(format(t, "minutes"))
print(format(t, ""))Python класс данных (класс данных в python)
1.02 ч 61.1 мин 3665 сек
Class method python (методы классов в python)
Как не переопределять встроенные методы, а использовать отдельный метод?
Можно создать собственный метод, например show(), и вызывать его явно. Это оставляет print в стандартном виде, но даёт возможность кастомизированного вывода.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
return f"{self.name}, возраст {self.age}"
person = Person("Анна", 25)
print(person.show())Python object methods (методы объектов в python)
Анна, возраст 25
Расширенные примеры и нестандартные ситуации
1. Совместное использование __str__ и __repr__ в иерархии классов
class Animal:
def __init__(self, name):
self.name = name
def __repr__(self):
return f"{self.__class__.__name__}(name='{self.name}')"
def __str__(self):
return f"Животное: {self.name}"
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name)
self.breed = breed
def __str__(self):
return f"Собака {self.name} породы {self.breed}"
dog = Dog("Рекс", "овчарка")
print(dog)
print(repr(dog))Собака Рекс породы овчарка Dog(name='Рекс')
В дочернем классе переопределён только __str__, __repr__ наследуется от родителя. Это удобно для отладки и пользовательского вывода.
2. Использование dataclasses с автогенерацией __repr__
from dataclasses import dataclass
@dataclass
class Point:
x: float
y: float
def __str__(self):
return f"({self.x:.1f}, {self.y:.1f})"
p = Point(3.1415, 2.71828)
print(p)
print(repr(p))(3.1, 2.7) Point(x=3.1415, y=2.71828)
Декоратор @dataclass автоматически создаёт __repr__, а __str__ переопределён вручную для более краткого вывода.
3. Вывод объектов в коллекциях
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def __repr__(self):
return f"{self.name}: ${self.price:.2f}"
products = [Product("Мышь", 25.99), Product("Клавиатура", 59.49)]
print(products)[Мышь: $25.99, Клавиатура: $59.49]
При печати списка Python использует __repr__ для каждого элемента. Поэтому лучше определить __repr__ для информативного отображения в коллекциях.
4. Условный вывод в зависимости от режима
class User:
def __init__(self, username, email, admin=False):
self.username = username
self.email = email
self.admin = admin
def __str__(self):
if self.admin:
return f"[ADMIN] {self.username}"
return f"{self.username} ({self.email})"
user1 = User("alice", "alice@example.com")
user2 = User("bob", "bob@example.com", admin=True)
print(user1)
print(user2)alice (alice@example.com) [ADMIN] bob
Такой подход позволяет изменять представление в зависимости от состояния объекта.
5. Использование __getattr__ и динамическое формирование строки
class Dynamic:
def __init__(self, **kwargs):
self.kwargs = kwargs
def __getattr__(self, name):
if name in self.kwargs:
return self.kwargs[name]
raise AttributeError
def __str__(self):
parts = [f"{k}={v}" for k, v in self.kwargs.items()]
return " | ".join(parts)
d = Dynamic(color="red", size=42, enabled=True)
print(d)color=red | size=42 | enabled=True
Здесь атрибуты создаются динамически, а __str__ собирает их в читаемую строку.