Ответ
Многие классические паттерны проектирования встроены непосредственно в синтаксис Python или его стандартную библиотеку, что делает их использование естественным и идиоматичным.
Вот несколько ключевых примеров:
1. Декоратор (Decorator)
Позволяет динамически добавлять новую функциональность к объекту, не изменяя его исходный код. В Python реализован через синтаксис @
.
def log_function_call(func):
def wrapper(*args, **kwargs):
print(f"Вызов функции: {func.__name__}")
result = func(*args, **kwargs)
return result
return wrapper
@log_function_call
def add(a, b):
return a + b
add(5, 3) # Вывод: Вызов функции: add
2. Итератор (Iterator)
Предоставляет стандартный способ обхода элементов коллекции. В Python протокол итератора (__iter__
и __next__
) лежит в основе работы цикла for
.
my_list = [1, 2, 3]
# Цикл for неявно использует итератор
for item in my_list:
print(item)
# Явное использование протокола
it = iter(my_list) # Получаем итератор
print(next(it)) # 1
print(next(it)) # 2
3. Синглтон (Singleton)
Гарантирует, что у класса есть только один экземпляр. В Python этот паттерн чаще всего реализуется на уровне модулей: при первом импорте модуль кэшируется в sys.modules
, и все последующие импорты возвращают ссылку на уже существующий объект модуля.
# config.py (наш синглтон)
SETTINGS = {
'api_key': 'YOUR_SECRET_KEY'
}
# main.py
from config import SETTINGS
print(SETTINGS['api_key'])
# another_module.py
from config import SETTINGS # Получаем тот же самый объект SETTINGS
4. Стратегия (Strategy)
Определяет семейство алгоритмов, инкапсулирует каждый из них и делает их взаимозаменяемыми. Классический пример в Python — аргумент key
в функции sorted()
.
users = [
{'name': 'Alice', 'age': 30},
{'name': 'Bob', 'age': 25}
]
# Стратегия сортировки по возрасту
sorted_by_age = sorted(users, key=lambda user: user['age'])
# Стратегия сортировки по имени
sorted_by_name = sorted(users, key=lambda user: user['name'])