我想为我的某个模块的用户提供能力,通过提供一个调用用户函数的接口来扩展其功能。例如,我想让用户能够在创建类的实例时得到通知,并且有机会在实例使用之前修改实例。
我实现它的方式是声明一个实例化的模块级工厂函数:
# 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这样的模块对我来说似乎过于矫枉过正了,尤其是后者,但是如果对于使用我的模块的程序员有很大的好处,我会向他们开放。
使用装饰器,维护附加回调列表的类,再加上从C#借用的概念,我得出了如下结论:
class delegate(object):
def __init__(self, func):
self.callbacks = []
self.basefunc = func
def __iadd__(self, func):
if callable(func):
self.__isub__(func)
self.callbacks.append(func)
return self
def callback(self, func):
if callable(func):
self.__isub__(func)
self.callbacks.append(func)
return func
def __isub__(self, func):
try:
self.callbacks.remove(func)
except ValueError:
pass
return self
def __call__(self, *args, **kwargs):
result = self.basefunc(*args, **kwargs)
for func in self.callbacks:
newresult = func(result)
result = result if newresult is None else newresult
return result
用@delegate
允许其他功能“附加”到它。
@delegate
def intfactory(num):
return int(num)
函数可以添加到委托+=
(和删除-=
)。你也可以用装饰funcname.callback
来添加一个回调函数。
@intfactory.callback
def notify(num):
print "notify:", num
def increment(num):
return num+1
intfactory += increment
intfactory += lambda num: num * 2
print intfactory(3) # outputs 8
class C(object):
_oncreate = []
def __new__(cls):
return reduce(lambda x, y: y(x), cls._oncreate, super(C, cls).__new__(cls))
@classmethod
def oncreate(cls, func):
cls._oncreate.append(func)
c = C()
print hasattr(c, 'spew')
@C.oncreate
def spew(obj):
obj.spew = 42
return obj
c = C()
print c.spew
相似问题