Pre-loader


Хуки в Python

В Python, як і в інших системах, можна використовувати хуки для розширення функціоналу.

Хуки та декоратори

Хуки (hooks) в програмуванні часто використовуються для встраивання додаткового коду у певні точки виконання програми. У Python хуки можна використовувати, наприклад, для встраивання додаткового функціоналу під час виклику певних функцій або подій.

Один з популярних способів використання хуків у Python - це використання декораторів. Наприклад, декоратор можна використовувати для виклику додаткового коду перед або після виклику певної функції. Ось приклад:

def before_hook(func):
    def wrapper(*args, **kwargs):
        print("Викликається хук до виклику функції")
        result = func(*args, **kwargs)
        return result
    return wrapper

def after_hook(func):
    def wrapper(*args, **kwargs):
        result = func(*args, **kwargs)
        print("Викликається хук після виклику функції")
        return result
    return wrapper

@before_hook
@after_hook
def my_function():
    print("Викликається основна функція")

# Виклик функції з хуками
my_function()

У цьому прикладі before_hook та after_hook - це два хуки, які викликаються перед та після виклику функції my_function. Декоратори @before_hook та @after_hook вказують, які хуки викликати для цієї функції.

Це лише простий приклад, і ви можете розширити цю ідею відповідно до своїх потреб. Реальна реалізація хуків може варіюватися залежно від конкретного використання в вашому коді або бібліотеці.

Хуки за рахунок наслідування

Ось приклад поєднання хуків з об'єктами та вставкою функціоналу в клас:

class HookMixin:
    def before_hook(self):
        print("Викликається хук до виклику методу")

    def after_hook(self):
        print("Викликається хук після виклику методу")


class MyClass(HookMixin):
    def my_method(self):
        self.before_hook()
        print("Викликається основний метод")
        self.after_hook()


# Створення об’єкту класу та виклик методу з хуками
obj = MyClass()
obj.my_method()

У цьому прикладі HookMixin - це міксин, який містить хуки (before_hook та after_hook). Клас MyClass успадковує від HookMixin та містить метод my_method, в якому викликаються хуки до та після виклику основного методу.

Використовуючи такий підхід, можна легко розширювати функціонал класів, додаючи нові хуки чи змінюючи існуючі, щоб вставляти додатковий код в певні точки виконання програми.

Використання хуки для доповнення функціоналу сторонніми програмістами

Відкритий функціонал для доповнення системи сторонніми програмістами можна реалізувати через використання хуків у системі. Суть цього підходу полягає в тому, щоб створити певні точки в коді, в які можна вставити власний код сторонніх програмістів без необхідності змінювати основний код системи. Ось приклад, як це можна реалізувати:

# Основний код системи

class System:
    def __init__(self):
        self.hooks = []

    def register_hook(self, hook):
        self.hooks.append(hook)

    def run_functionality(self):
        print("Викликається основна функціональність")
        for hook in self.hooks:
            hook()


# Код, який може написати сторонній програміст

def additional_functionality():
    print("Вставка додаткової функціональності")


# Використання системи та додання функціоналу через хук

system_instance = System()

# Сторонній програміст реєструє свій хук
system_instance.register_hook(additional_functionality)

# Основний код системи викликається, включаючи всі зареєстровані хуки
system_instance.run_functionality()

У цьому прикладі System - це основний клас системи, який має можливість реєстрації хуків (register_hook) та виклику функціоналу (run_functionality). Сторонній програміст може написати власну функцію (additional_functionality), яку він хоче вставити у систему.

Спочатку сторонній програміст реєструє свій хук у системі, а потім, коли викликається основна функціональність, усі зареєстровані хуки також викликаються.

Цей підхід дозволяє стороннім програмістам додавати свій функціонал до існуючої системи, не змінюючи при цьому основний код системи.

Передача параметрів в хуки

Давайте доповнимо та розширимо приклад. Додамо можливість передавати додаткові параметри в хуки та видаляти хуки з системи. Також, розширимо функціонал стороннього програміста, дозволяючи йому отримувати та змінювати дані у системі:

# Основний код системи

class System:
    def __init__(self):
        self.hooks = []
        self.data = {"system_data": "Some data from the system"}

    def register_hook(self, hook):
        self.hooks.append(hook)

    def unregister_hook(self, hook):
        if hook in self.hooks:
            self.hooks.remove(hook)

    def run_functionality(self):
        print("Викликається основна функціональність")
        for hook in self.hooks:
            hook(self.data)


# Код, який може написати сторонній програміст

def additional_functionality_1(data):
    print("Вставка додаткової функціональності 1")
    print("Дані з системи:", data["system_data"])
    data["additional_data_1"] = "Some additional data 1"


def additional_functionality_2(data):
    print("Вставка додаткової функціональності 2")
    data["additional_data_2"] = "Some additional data 2"


# Використання системи та додання функціоналу через хуки

system_instance = System()

# Сторонні програмісти реєструють свої хуки
system_instance.register_hook(additional_functionality_1)
system_instance.register_hook(additional_functionality_2)

# Основний код системи викликається, включаючи всі зареєстровані хуки
system_instance.run_functionality()

# Сторонній програміст може видалити один з хуків
system_instance.unregister_hook(additional_functionality_1)

# Основний код системи викликається знову
system_instance.run_functionality()

У цьому прикладі, кожен хук отримує об'єкт data як аргумент, де вони можуть читати та змінювати дані у системі. Сторонній програміст, наприклад, може додавати свої дані до системи або зчитувати існуючі дані.

Також, додана можливість видалення хуків з системи за допомогою методу unregister_hook. Зауважте, що в прикладі additional_functionality_1 видаляється хук перед наступним викликом run_functionality.

Реєстрація власних подій сторонніми програмістами

Давайте ще трошки розвинемо ідею, додаючи можливість стороннім програмістам реєструвати власні події та підписники на ці події. Це може полегшити спосіб, яким додатковий функціонал може взаємодіяти з системою.

# Основний код системи

class System:
    def __init__(self):
        self.hooks = {}
        self.data = {"system_data": "Some data from the system"}

    def register_hook(self, event, hook):
        if event not in self.hooks:
            self.hooks[event] = []
        self.hooks[event].append(hook)

    def unregister_hook(self, event, hook):
        if event in self.hooks and hook in self.hooks[event]:
            self.hooks[event].remove(hook)

    def run_event(self, event):
        print(f"Викликається подія: {event}")
        for hook in self.hooks.get(event, []):
            hook(self.data)


# Код, який може написати сторонній програміст

def on_startup(data):
    print("Викликається під час запуску")
    data["startup_message"] = "Система успішно запущена"


def on_shutdown(data):
    print("Викликається перед завершенням роботи")
    print("Дані системи:", data)


# Використання системи та додання функціоналу через хуки та події

system_instance = System()

# Сторонні програмісти реєструють свої хуки на події
system_instance.register_hook("startup", on_startup)
system_instance.register_hook("shutdown", on_shutdown)

# Основний код системи викликає події, включаючи всі підписники (хуки)
system_instance.run_event("startup")
system_instance.run_event("shutdown")

У цьому прикладі додано методи register_hook і unregister_hook для реєстрації та видалення хуків на певні події. Тепер сторонні програмісти можуть реєструвати свої функції (on_startup, on_shutdown) на конкретні події, і ці функції будуть викликатися під час відповідних подій.

Цей підхід робить систему більш гнучкою, дозволяючи стороннім програмістам додавати функціонал до конкретних подій у системі.

Автор: Рудюк С.А. 2023. K2 Cloud ERP.