позволяют пользователям «расширять» функции API

Я пишу modding API для своей игры, и я хочу разрешить пользователям сообщать игровому движку запускать функцию своего мода непосредственно перед или после одной из функций API, другими словами, «расширять» функции.

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

Прямо сейчас я думаю о чем-то вроде этого:

def moddersFunction(): pass myAPI.extendFunction('functionName', 'before-or-after', moddersFunction, extraArgs=[]) 

Теперь, что будет сравнительно чистым способом реализации этого? Другими словами, как выглядят внутренние myAPI.extendFunction если вы хотите написать это?

Я думаю, что у меня есть словарь, который myAPI.extendFunction будет добавлять функции, а функции в моем API будут проверять и запускать функцию мод, если она была установлена ​​(«зарегистрирована»). Но это означает добавление кода, который проверяет словарь в каждой отдельной функции в моем моддинговом API, который я хочу разрешить продлить (даже если это всего лишь один вызов функции, который выполняет функцию проверки и функции, сам по себе кажется) ,

Мне интересно, есть ли какой-нибудь опрятный трюк Python, который позволит такое «расширение» функций без «разборки» (возможно, я преувеличиваю) существующего исходного кода API моей игры.

Я бы сделал что-то в следующих строках:

 class hookable(object): def __init__(self, fn): self.pre = [] self.post = [] self.fn = fn def add_pre(self, hook): self.pre.append(hook) def add_post(self, hook): self.post.append(hook) def __call__(self, *args, **kwargs): for hook in self.pre: hook(*args, **kwargs) ret = self.fn(*args, **kwargs) for hook in self.post: hook(*args, **kwargs) return ret 

Любая «расширяемая» функция теперь может быть оформлена так:

 @hookable def square(x): return x**2 

Теперь вы можете использовать square.add_pre() и square.add_post() для регистрации функций, которые автоматически вызываются до и после каждого вызова square.add_post() square() :

 print square(2) def pre(x): print 'pre', x def post(x): print 'post', x square.add_pre(pre) print square(2) print square(3) square.add_post(post) print square(4) print square(5) 

Я бы, наверное, сделал что-то подобное. Очевидно, то, что вы на самом деле делаете, зависит от ваших требований.

 class Extend(object): def __init__(self, original_function): self.original_function = original_function def __call__(self, function): def _wrapped(*args, **kwargs): yield function(*args, **kwargs) yield self.original_function(*args, **kwargs) return _wrapped import time @Extend(time.asctime) def funky_time(): return "This is the time in the UK" print list(funky_time())