Управление печатью экземпляров класса
Настройка печати объектов класса
Наиболее эффективный способ задать вывод экземпляра класса при вызове print() или str() - переопределить магический метод __str__. Для целей отладки и для представления, возвращаемого repr(), следует также определить __repr__. Эти методы возвращают строку, которая и будет отображаться.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"Person({self.name}, {self.age})"
def __repr__(self):
return f"Person(name={self.name!r}, age={self.age!r})"
p = Person("Alice", 30)
print(p) # Person(Alice, 30)
print(repr(p)) # Person(name='Alice', age=30)атрибуты класса python (атрибуты классов и объектов в python)
Person(Alice, 30) Person(name='Alice', age=30)
библиотека классов python (библиотека классов в python)
Типичная ошибка: не переопределить ни один из методов, тогда print() выведет нечто вроде <__main__.Person object at 0x...>, что бесполезно для человека. Также опасно забыть вернуть строку - если метод возвращает другой тип, возникнет исключение TypeError.
Как вывести объект для разработчика?
Если требуется получить максимально полную информацию, включая типы данных, используйте __repr__. По соглашению, результат __repr__ должен быть таким, чтобы его можно было скопировать и создать аналогичный объект (если возможно).
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point(x={self.x!r}, y={self.y!r})"
pt = Point(3.5, 2.0)
print(repr(pt))
метод объекта python (методы объектов в python)
Point(x=3.5, y=2.0)
метод call python (метод __call__ в python)
Если __repr__ не определён, используется реализация из object, которая выводит имя класса и адрес в памяти. Для отладки это неинформативно.
Как вывести объект для пользователя?
Для дружественного пользователю представления предназначен __str__. Он вызывается функциями print() и str(). Если __str__ не задан, Python использует __repr__ как запасной вариант.
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
def __str__(self):
return f"«{self.title}» ({self.author})"
b = Book("1984", "George Orwell")
print(b)Python структура объекта (структура объекта в python)
«1984» (George Orwell)
Python создание объектов (создание объектов в python)
Часто начинающие определяют только __str__, но забывают про __repr__. Это приводит к тому, что в списках или при логировании объекты отображаются нечитаемо (так как для контейнеров вызывается __repr__).
Как отформатировать объект с помощью f-строк или метода format?
Метод __format__ позволяет управлять отображением при использовании спецификаций формата, например {0:20s}.
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def __str__(self):
return f"{self.name}: ${self.price:.2f}"
def __format__(self, spec):
if spec == 'short':
return self.name
elif spec == 'long':
return f"Product({self.name!r}, {self.price!r})"
return str(self)
prod = Product("Laptop", 1299.99)
print(f"{prod:short}")
print(f"{prod:long}")Self object python (объект self в python)
Laptop
Product('Laptop', 1299.99)Object attribute python (атрибуты объекта в python)
Без определения __format__ пользовательские спецификации приводят к ошибке TypeError.
Как автоматически получить читаемый вывод с помощью dataclass?
Декоратор @dataclass автоматически генерирует __repr__ (и при необходимости __str__), что избавляет от ручного написания.
from dataclasses import dataclass
@dataclass
class Employee:
name: str
salary: float
emp = Employee("Bob", 50000.0)
print(emp)Python call method (вызов метода в python)
Employee(name='Bob', salary=50000.0)
Python класс данных (класс данных в python)
Если в dataclass есть поля с большими объёмами данных, автоматический __repr__ может стать излишне подробным. В таких случаях можно переопределить метод вручную.
Как вывести объект в красиво отформатированном виде с pprint?
Модуль pprint использует __repr__ для каждого элемента. Для вложенных структур это даёт аккуратный вывод с отступами.
from pprint import pprint
class Node:
def __init__(self, value, children=None):
self.value = value
self.children = children or []
def __repr__(self):
return f"Node({self.value!r}, children={self.children!r})"
tree = Node(1, [Node(2), Node(3, [Node(4)])])
pprint(tree)Class method python (методы классов в python)
Node(1, children=[Node(2, children=[]), Node(3, children=[Node(4, children=[])])])
Python object methods (методы объектов в python)
pprint не работает, если __repr__ возвращает очень длинные строки без разбивки. В таких случаях помогает pprint.PrettyPrinter с настройкой ширины.
Как сериализовать объект в JSON для вывода?
Если нужно вывести объект в формате JSON, следует сначала преобразовать его в словарь (через __dict__ или кастомный метод), а затем использовать json.dumps с параметром default.
import json
class Car:
def __init__(self, make, model):
self.make = make
self.model = model
def to_dict(self):
return {"make": self.make, "model": self.model}
car = Car("Tesla", "Model 3")
print(json.dumps(car.to_dict(), indent=2))класс python определение (определение классов в python)
{
"make": "Tesla",
"model": "Model 3"
}Self method python (параметр self в методах python)
Попытка напрямую передать объект в json.dumps вызывает TypeError: Object of type Car is not JSON serializable. Необходимо обеспечить сериализуемость.
Как вручную сформировать вывод, обращаясь к атрибутам?
Иногда проще не переопределять магические методы, а написать отдельную функцию или метод, который возвращает нужную строку. Это удобно, когда формат зависит от контекста.
class Student:
def __init__(self, name, grades):
self.name = name
self.grades = grades
def display(self, detailed=False):
if detailed:
return f"{self.name}: {', '.join(str(g) for g in self.grades)}"
return self.name
s = Student("Kate", [85, 92, 78])
print(s.display())
print(s.display(detailed=True))приватные атрибуты python (приватные атрибуты в python)
Kate Kate: 85, 92, 78
При таком подходе теряется интеграция со стандартными функциями вроде print() и str(). Необходимо явно вызывать кастомный метод.
Выбор конкретного варианта зависит от цели: для отладки - __repr__, для пользователя - __str__, для сериализации - JSON, для красивого отображения вложенных структур - pprint.
Расширенные примеры печати классов
Вложенные объекты с __repr__ и ограничение глубины через reprlib
import reprlib
class Folder:
def __init__(self, name, subfolders=None):
self.name = name
self.subfolders = subfolders or []
def __repr__(self):
subs = reprlib.repr(self.subfolders)
return f"Folder({self.name!r}, subfolders={subs})"
root = Folder("root", [Folder("docs", [Folder("notes")]), Folder("assets")]*10)
print(repr(root))
Folder('root', subfolders=[Folder('docs', subfolders=[Folder('notes', subfolders=[])]), Folder('assets', subfolders=[]), ... (18 more)])
Многострочный __str__ с выравниванием
class Table:
def __init__(self, rows):
self.rows = rows # список списков
def __str__(self):
lines = []
for row in self.rows:
lines.append(' | '.join(str(cell) for cell in row))
return '\n'.join(lines)
t = Table([["Name", "Age"], ["Alice", 30], ["Bob", 25]])
print(t)
Name | Age Alice | 30 Bob | 25
Кастомный JSON encoder с заменой __repr__ для сериализации
import json
class Color:
def __init__(self, r, g, b):
self.r = r
self.g = g
self.b = b
def __repr__(self):
return f"Color(r={self.r}, g={self.g}, b={self.b})"
class ColorEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Color):
return {'r': obj.r, 'g': obj.g, 'b': obj.b}
return super().default(obj)
c = Color(255, 0, 0)
print(json.dumps(c, cls=ColorEncoder))
{"r": 255, "g": 0, "b": 0}
Использование rich для цветного и структурированного вывода
from rich.console import Console
from rich.table import Table as RichTable
class Project:
def __init__(self, name, tasks):
self.name = name
self.tasks = tasks
def __rich__(self):
table = RichTable(title=self.name)
table.add_column("Task")
table.add_column("Status")
for t, s in self.tasks:
table.add_row(t, s)
return table
console = Console()
proj = Project("Deploy", [("build", "done"), ("test", "in progress")])
console.print(proj)
(выводится таблица с заголовком "Deploy" и двумя колонками)
Применение tabulate для табличного вывода атрибутов объектов
from tabulate import tabulate
class Record:
def __init__(self, key, value):
self.key = key
self.value = value
records = [Record("alpha", 1), Record("beta", 2)]
headers = ["Key", "Value"]
rows = [(r.key, r.value) for r in records]
print(tabulate(rows, headers=headers))
Key Value ------ ------- alpha 1 beta 2
Переопределение __bytes__ для двоичного представления
class Packet:
def __init__(self, data):
self.data = data
def __bytes__(self):
return bytes(self.data, 'utf-8')
p = Packet("Hello")
print(bytes(p))
b'Hello'
Эти примеры демонстрируют гибкость Python при настройке вывода объектов. Выбор подхода зависит от контекста: краткость для консоли, структурированность для отладки, сериализация для обмена данными.