完成了一般的委托功能,一个委托上挂多个函数,可以设置函数列表为空时,是否抛出异常。返回值是函数列表中最后一个函数调用的返回,使用方法可参见test部分。

class delegate:
        def __init__(self, *calls, **opts):
                for call in calls:
                        if not callable(call):
                                raise RuntimeError, str(call) + ' not a callable object'
                self.calls = () + calls
                self.emptyExcept = opts.get('emptyExcept', False)
        def __call__(self, *args):
                if self.emptyExcept and not self.calls:
                        raise RuntimeError, 'No callable objects'

                try:
                        result = None
                        for call in self.calls:
                                result = call (*args)
                        return result
                except TypeError:
                        raise RuntimeError, 'Invalid callable type: ' + str(call)

        def __add__(self, call):
                if not callable(call):
                        raise RuntimeError, str(call) + ' not a callable object'
                return delegate(*(self.calls + (call,)))
        def __iadd__(self, *calls):
                self.calls += calls
                return self


if __name__ == '__main__':
        def a(v1, v2):
                print 'a:', v1, v2
        def b(v1, v2):
                print 'b:', v1, v2
        def c(v1, v2):
                print 'c:', v1, v2

        class Test:
                def hello(self, v1, v2):
                        print 'Test.hello:', v1, v2

        class Test1:
                def __call__(self, v1, v2):
                        print 'Test1.__call__:', v1, v2

        print '======== test delegate.__init__ and delegate.__call__'
        f = delegate(a, b, c, Test().hello, Test1())
        f (3, 4)
        print '======== test delegate.__add__'
        f1 = f + a
        f1 (5, 6)
        print '======== test delegate.__iadd__'
        f2 = delegate(a, b)
        f2 += c
        f2 (9, 10)
        print '======== test delegate.__call__ return value'
        f3 = delegate(lambda x, y: x*y)
        assert f3(10, 11) == 10*11
        f3 = delegate(lambda x, y: x*y, lambda x, y: x**y)
        assert f3(10, 11) == 10**11
        print '======== test delegate.__call__ with empty exception (empty)'
        f4 = delegate (emptyExcept=True)
        try:
                f4 (3, 5)
        except RuntimeError, ex:
                print 'Exception:', ex
        print '======== test delegate.__call__ with empty exception (not empty)'
        f4 += a
        f4 (3, 5)