Ответ
Хотя многие паттерны применимы в Python, некоторые используются особенно часто благодаря особенностям языка.
-
Декоратор (Decorator) В Python этот паттерн реализован на уровне синтаксиса (
@decorator), что делает его чрезвычайно популярным для добавления функциональности (логирование, кэширование, проверка прав) к функциям и методам, не изменяя их код.import time def timing_decorator(func): def wrapper(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) end_time = time.time() print(f"'{func.__name__}' выполнилась за {end_time - start_time:.4f} секунд") return result return wrapper @timing_decorator def get_data(): time.sleep(1) return "Some data" get_data() # Вывод: 'get_data' выполнилась за 1.0012 секунд -
Фабричный метод (Factory Method) Позволяет создавать объекты, делегируя логику инстанцирования подклассам. Это полезно, когда система должна работать с объектами разных типов, но их точный тип определяется во время выполнения.
class Document: # ... базовый класс class PdfDocument(Document): # ... реализация для PDF class WordDocument(Document): # ... реализация для Word def get_document_creator(file_extension): if file_extension == 'pdf': return PdfDocument elif file_extension == 'docx': return WordDocument raise ValueError("Unknown format") # Использование DocCreator = get_document_creator('pdf') my_doc = DocCreator() -
Стратегия (Strategy) Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Часто используется для реализации различных способов обработки данных (сортировка, экспорт).
from abc import ABC, abstractmethod class ExportStrategy(ABC): @abstractmethod def export(self, data): pass class JsonExport(ExportStrategy): def export(self, data): print(f"Экспорт в JSON: {data}") class XMLExport(ExportStrategy): def export(self, data): print(f"Экспорт в XML: {data}") # Контекст, использующий стратегию class Exporter: def __init__(self, strategy: ExportStrategy): self._strategy = strategy def run(self, data): self._strategy.export(data) data_to_export = {"id": 1, "name": "item"} exporter = Exporter(JsonExport()) exporter.run(data_to_export) -
Наблюдатель (Observer) Создает механизм подписки, позволяющий одним объектам следить и реагировать на события, происходящие в других объектах. Основа для многих event-driven систем.
-
Одиночка (Singleton) Гарантирует, что у класса есть только один экземпляр. В Python часто считается антипаттерном, так как его функциональность можно реализовать более идиоматично через модули, которые по своей природе являются синглтонами.
Ответ 18+ 🔞
Ну, слушай, паттерны проектирования — это как, блядь, кулинарные рецепты для программиста. Вроде бы можно и без них, но потом получается каша из спагетти, которую ни в рот взять, ни в код закоммитить. А в Python, ёпта, некоторые из них прижились так, будто их тут и рожали.
Вот, например, Декоратор. Это вообще, блядь, визитная карточка языка. Синтаксис такой милый, собачка @, а под капотом — мощнейший инструмент, чтобы обернуть функцию, не трогая её саму. Логирование, замер времени, кэширование — всё туда.
import time
def timing_decorator(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"'{func.__name__}' выполнилась за {end_time - start_time:.4f} секунд")
return result
return wrapper
@timing_decorator
def get_data():
time.sleep(1)
return "Some data"
get_data()
# Вывод: 'get_data' выполнилась за 1.0012 секунд
Красота же, блядь! Навесил собачку и функция уже не просто работает, а ещё и отчитывается, сколько она там прохлаждалась.
Дальше, Фабричный метод. Ситуация классическая: «Ой, а что создавать-то будем? А хрен его знает, узнаем в рантайме». Вот этот паттерн как раз про то, чтобы не городить if-ов на каждом углу, а вынести эту логику в отдельное место.
class Document:
# ... базовый класс
class PdfDocument(Document):
# ... реализация для PDF
class WordDocument(Document):
# ... реализация для Word
def get_document_creator(file_extension):
if file_extension == 'pdf':
return PdfDocument
elif file_extension == 'docx':
return WordDocument
raise ValueError("Unknown format")
# Использование
DocCreator = get_document_creator('pdf')
my_doc = DocCreator()
Типа, «дай-ка мне фабрику для пдфшек» — и вот тебе, сука, готовый конструктор. Удобно, не приходится мозг ломать.
А вот Стратегия — это вообще песня. Когда у тебя есть, например, пять разных способов отсортировать данные или экспортировать их в файл. И вместо того, чтобы делать монструозную функцию с кучей switch-ей, ты каждый алгоритм в отдельный класс засовываешь.
from abc import ABC, abstractmethod
class ExportStrategy(ABC):
@abstractmethod
def export(self, data):
pass
class JsonExport(ExportStrategy):
def export(self, data):
print(f"Экспорт в JSON: {data}")
class XMLExport(ExportStrategy):
def export(self, data):
print(f"Экспорт в XML: {data}")
# Контекст, использующий стратегию
class Exporter:
def __init__(self, strategy: ExportStrategy):
self._strategy = strategy
def run(self, data):
self._strategy.export(data)
data_to_export = {"id": 1, "name": "item"}
exporter = Exporter(JsonExport())
exporter.run(data_to_export)
Меняешь стратегию на лету — и весь остальной код даже не подозревает, что что-то поменялось. Хитро, блядь!
Наблюдатель — это про то, чтобы все узнали, что Васёк, наконец, закоммитил код без багов. Создаёшь механизм подписки: «кто хочет следить за этим идиотом?». И когда событие случается — всех оповещаешь. Основа для всего event-driven, без этого никуда.
Ну и куда же без Одиночки. Гарантирует, что класс будет в единственном экземпляре. Хотя в Python, если честно, его часто считают антипаттерном, ядрёна вошь! Потому что модули у нас и так по своей природе синглтоны. Зачем городить огород с приватными конструкторами, когда можно просто импортировать модуль и всё? Но некоторые всё равно любят, это ж классика, как «Муму», блядь, все проходили.
Короче, паттерны — это не священная корова, а инструменты. Главное — понимать, зачем они нужны, а не тыкать их куда попало, лишь бы в резюме написать. А то будет как у того Герасима — сила есть, а сказать нечего, только «Му-му» мычать.