Что такое monkey patching?python-36

Monkey patching (горячая замена, динамическая модификация) — это техника динамического изменения поведения кода во время выполнения программы путем модификации классов, модулей или объектов после их создания.

Основная концепция

Monkey patching позволяет:

  1. Модифицировать существующие классы/объекты без изменения исходного кода
  2. Добавлять или заменять методы и атрибуты во время выполнения
  3. Исправлять поведение сторонних библиотек без их переписывания

Простейший пример:

class Calculator:
    def add(self, a, b):
        return a + b

# Monkey patch: добавляем новый метод
Calculator.multiply = lambda self, a, b: a * b

calc = Calculator()
print(calc.multiply(3, 4))  # Выведет 12

Типичные сценарии использования

1. Исправление поведения сторонних библиотек

import some_library

# Заменяем проблемный метод
some_library.BuggyClass.method = fixed_implementation

2. Добавление функциональности к существующим классам

# Добавляем метод к встроенному классу
list.mean = lambda self: sum(self) / len(self) if self else 0

data = [1, 2, 3]
print(data.mean())  # Выведет 2.0

3. Тестирование и мокирование

# В тестах подменяем реальный API на mock-объект
import production_code

production_code.call_external_api = mock_api_response

Продвинутые техники

1. Временный monkey patch с контекстным менеджером

from contextlib import contextmanager

@contextmanager
def temp_patch(obj, attr, new_value):
    original = getattr(obj, attr)
    setattr(obj, attr, new_value)
    try:
        yield
    finally:
        setattr(obj, attr, original)

with temp_patch(requests, 'get', mock_get):
    # Здесь requests.get будет подменен
    response = requests.get('https://example.com')

2. Патчинг модулей

import sys
import fake_ssl

# Подменяем модуль ssl
sys.modules['ssl'] = fake_ssl

Опасности и ограничения

  1. Неочевидное поведение: изменения могут быть неожиданными для других частей кода
  2. Проблемы совместимости: могут ломаться при обновлении библиотек
  3. Сложность отладки: сложно отследить источник изменений

Альтернативы

  1. Наследование: создание подклассов вместо модификации
  2. Адаптеры: оберточные классы с нужным поведением
  3. Dependency Injection: передача зависимостей через параметры

Резюмируем

Monkey patching — мощный, но опасный инструмент, который стоит использовать для:

  • Быстрых фиксов в экстренных случаях
  • Тестирования и прототипирования
  • Временных решений, когда изменение исходного кода невозможно

Пример с подсветкой (VSCode style):

import datetime

# Monkey patch для добавления новой функциональности
def days_to_new_year(self):
    today = self.today()
    new_year = datetime.date(today.year + 1, 1, 1)
    return (new_year - today).days

datetime.date.days_to_new_year = days_to_new_year

# Использование
print(datetime.date.today().days_to_new_year())