Я хотел бы предоставить возможность пользователям одного из моих модулей расширять свои возможности, предоставляя интерфейс для вызова пользовательской функции. Например, я хочу дать пользователям возможность получать уведомления, когда создается экземпляр класса, и предоставляется возможность изменить экземпляр до его использования.
Способ, которым я реализовал это, - объявить функцию уровня factory на уровне модуля, которая создает экземпляр:
# in mymodule.py
def factory(cls, *args, **kwargs):
return cls(*args, **kwargs)
Тогда, когда мне нужен экземпляр класса в mymodule, я делаю factory(cls, arg1, arg2)
, а не cls(arg1, arg2)
.
Чтобы расширить его, программист напишет в другом модуле такую функцию:
def myFactory(cls, *args, **kwargs):
instance = myFactory.chain(cls, *args, **kwargs)
# do something with the instance here if desired
return instance
Установка вышеуказанного обратного вызова выглядит следующим образом:
myFactory.chain, mymodule.factory = mymodule.factory, myFactory
Для меня это кажется достаточно простым, но мне было интересно, будет ли вы, как программист на Python, ожидать, что функция зарегистрирует обратный вызов, а не делает это с назначением, или если бы были другие методы, которые вы ожидаете. Мое решение кажется работоспособным, идиоматичным и понятным для вас?
Я стараюсь держать его как можно проще; Я не думаю, что большинству приложений действительно потребуется цепочка более одного обратного вызова пользователя, например (хотя неограниченная цепочка поставляется "бесплатно" с приведенным выше шаблоном). Я сомневаюсь, что им нужно будет удалить обратные вызовы или указать приоритеты или порядок. Модули типа python-callbacks или PyDispatcher кажутся мне излишними, особенно последними, но если есть являются неотъемлемыми преимуществами для программиста, работающего с моим модулем, я открыт для них.