In Questo Articolo
1. Классы в Python
Классы — основной механизм ООП. Класс можно рассматривать как шаблон для создания объектов с атрибутами (данные) и методами (функции). Объекты класса называются экземплярами. Классы помогают структурировать код, улучшать его повторное использование и упрощать поддержку.
Структура класса
class ClassName:
def __init__(self, param1, param2):
self.param1 = param1
self.param2 = param2
def method(self):
return f'{self.param1} и {self.param2}'
Ключевые моменты:
__init__: конструктор для инициализации атрибутов объекта.self: ссылка на текущий экземпляр.- Атрибуты: определяются через
self, доступны во всех методах. - Методы: работают с данными объекта.
Создание объектов
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def description(self):
return f'{self.year} {self.make} {self.model}'
my_car = Car('Toyota', 'Corolla', 2020)
print(my_car.description()) # Вывод: 2020 Toyota Corolla
Типы методов
- Методы экземпляра — работают с объектами (
self). - Методы класса — работают с классом (
cls) через@classmethod. - Статические методы — независимы от экземпляра и класса (
@staticmethod).
Наследование
class Animal:
def speak(self):
return 'Звук животного'
class Dog(Animal):
def speak(self):
return 'Гав'
Полиморфизм
class Cat(Animal):
def speak(self):
return 'Мяу'
cat = Cat()
print(cat.speak()) # Вывод: Мяу
- Один и тот же метод работает по-разному в зависимости от типа объекта.
Инкапсуляция
class Car:
def __init__(self, make, model):
self._make = make # Защищённый атрибут
self._model = model
def get_make(self):
return self._make
def set_make(self, make):
self._make = make
Магические методы и деструктор
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(3, 4)
print(p) # Вывод: Point(3, 4)
ASCII-диаграмма: Наследование и Полиморфизм
┌─────────┐
│ Animal │
└─────────┘
│ speak() │
└─────────┘
▲
┌───────┴────────┐
│ │
┌─────────┐ ┌─────────┐
│ Dog │ │ Cat │
└─────────┘ └─────────┘
│ speak() │ │ speak() │
└─────────┘ └─────────┘
2. Контекстные менеджеры в Python
Контекстные менеджеры позволяют автоматически выделять и освобождать ресурсы, обеспечивая корректное завершение работы даже при ошибках.
Использование @contextmanager
from contextlib import contextmanager
@contextmanager
def my_context():
print("Вход в контекст")
try:
yield "Ресурс"
finally:
print("Выход из контекста")
Применение:
with my_context() as res:
print("Внутри контекста:", res)
Перехват stdout/stderr и Tee
Python позволяет перехватывать stdout, stderr или оба потока и даже одновременно выводить и перехватывать данные через паттерн Tee.
3. Полный пример: oop_and_context.py
"""
oop_and_context.py
Примеры классов, принципов ООП и контекстных менеджеров в Python.
Включает:
- Определение классов, наследование, полиморфизм, инкапсуляция
- Методы экземпляра, класса и статические
- Магические методы и деструктор
- Контекстные менеджеры с @contextmanager
- Перехват stdout, stderr, объединённый захват
- Паттерн Tee для одновременного вывода и захвата
- Классовый контекстный менеджер
"""
import sys
import io
from contextlib import contextmanager
# ==========================
# Часть 1: Классы и ООП
# ==========================
class Animal:
"""Базовый класс для животных."""
def speak(self):
return 'Звук животного'
class Dog(Animal):
def speak(self):
return 'Гав'
class Cat(Animal):
def speak(self):
return 'Мяу'
class Car:
"""Пример класса с инкапсуляцией."""
def __init__(self, make, model, year=None):
self._make = make
self._model = model
self.year = year
def get_make(self):
return self._make
def set_make(self, make):
self._make = make
def description(self):
if self.year:
return f'{self.year} {self._make} {self._model}'
return f'{self._make} {self._model}'
class Point:
"""Класс с магическими методами."""
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f'Point({self.x}, {self.y})'
# ==========================
# Часть 2: Контекстные менеджеры
# ==========================
@contextmanager
def my_context():
print("Вход в контекст")
try:
yield "Ресурс"
finally:
print("Выход из контекста")
@contextmanager
def capture_stdout():
old_stdout = sys.stdout
sys.stdout = buffer = io.StringIO()
try:
yield buffer
finally:
sys.stdout = old_stdout
@contextmanager
def capture_stderr():
old_stderr = sys.stderr
sys.stderr = buffer = io.StringIO()
try:
yield buffer
finally:
sys.stderr = old_stderr
@contextmanager
def capture_output():
old_stdout = sys.stdout
old_stderr = sys.stderr
sys.stdout = sys.stderr = buffer = io.StringIO()
try:
yield buffer
finally:
sys.stdout = old_stdout
sys.stderr = old_stderr
class Tee(io.StringIO):
"""Одновременный вывод и захват."""
def __init__(self, original):
super().__init__()
self.original = original
def write(self, text):
self.original.write(text)
super().write(text)
def flush(self):
self.original.flush()
@contextmanager
def capture_stdout_tee():
old_stdout = sys.stdout
sys.stdout = tee = Tee(old_stdout)
try:
yield tee
finally:
sys.stdout = old_stdout
# ==========================
# Часть 3: Классовый контекстный менеджер
# ==========================
class OutputCapture:
"""Классовый контекстный менеджер для перехвата stdout."""
def __init__(self):
self._buffer = io.StringIO()
self._old_stdout = None
def __enter__(self):
self._old_stdout = sys.stdout
sys.stdout = self._buffer
return self._buffer
def __exit__(self, exc_type, exc_val, exc_tb):
sys.stdout = self._old_stdout
return False # проброс исключений
# ==========================
# Часть 4: Демонстрации
# ==========================
def demo_classes():
print("\n--- Демонстрация классов ---")
dog = Dog()
cat = Cat()
print("Собака говорит:", dog.speak())
print("Кошка говорит:", cat.speak())
my_car = Car('Toyota', 'Corolla', 2020)
print("Описание машины:", my_car.description())
my_car.set_make('Honda')
print("Обновлённая марка:", my_car.get_make())
point = Point(3, 4)
print("Точка:", point)
def demo_context_managers():
print("\n--- Демонстрация контекстных менеджеров ---")
with my_context() as res:
print("Внутри контекста:", res)
with capture_stdout() as out:
print("Перехваченный stdout")
print("Содержимое:", out.getvalue().strip())
with capture_stderr() as err:
print("Это stdout")
sys.stderr.write("Сообщение об ошибке\n")
print("Ошибки:", err.getvalue().strip())
with capture_output() as out_all:
print("Stdout в объединённом захвате")
sys.stderr.write("Stderr в объединённом захвате\n")
print("Объединённый вывод:", out_all.getvalue().strip())
with capture_stdout_tee() as tee_out:
print("Одновременный вывод и захват через Tee")
print("Буфер Tee:", tee_out.getvalue().strip())
with OutputCapture() as class_capture:
print("Перехват через классовый контекстный менеджер")
print("Буфер классового менеджера:", class_capture.getvalue().strip())
# ==========================
# Основной запуск
# ==========================
if __name__ == "__main__":
demo_classes()
demo_context_managers()