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

   1 class delegate:
   2         def __init__(self, *calls, **opts):
   3                 for call in calls:
   4                         if not callable(call):
   5                                 raise RuntimeError, str(call) + ' not a callable object'
   6                 self.calls = () + calls
   7                 self.emptyExcept = opts.get('emptyExcept', False)
   8         def __call__(self, *args):
   9                 if self.emptyExcept and not self.calls:
  10                         raise RuntimeError, 'No callable objects'
  11 
  12                 try:
  13                         result = None
  14                         for call in self.calls:
  15                                 result = call (*args)
  16                         return result
  17                 except TypeError:
  18                         raise RuntimeError, 'Invalid callable type: ' + str(call)
  19 
  20         def __add__(self, call):
  21                 if not callable(call):
  22                         raise RuntimeError, str(call) + ' not a callable object'
  23                 return delegate(*(self.calls + (call,)))
  24         def __iadd__(self, *calls):
  25                 self.calls += calls
  26                 return self
  27 
  28 
  29 if __name__ == '__main__':
  30         def a(v1, v2):
  31                 print 'a:', v1, v2
  32         def b(v1, v2):
  33                 print 'b:', v1, v2
  34         def c(v1, v2):
  35                 print 'c:', v1, v2
  36 
  37         class Test:
  38                 def hello(self, v1, v2):
  39                         print 'Test.hello:', v1, v2
  40 
  41         class Test1:
  42                 def __call__(self, v1, v2):
  43                         print 'Test1.__call__:', v1, v2
  44 
  45         print '======== test delegate.__init__ and delegate.__call__'
  46         f = delegate(a, b, c, Test().hello, Test1())
  47         f (3, 4)
  48         print '======== test delegate.__add__'
  49         f1 = f + a
  50         f1 (5, 6)
  51         print '======== test delegate.__iadd__'
  52         f2 = delegate(a, b)
  53         f2 += c
  54         f2 (9, 10)
  55         print '======== test delegate.__call__ return value'
  56         f3 = delegate(lambda x, y: x*y)
  57         assert f3(10, 11) == 10*11
  58         f3 = delegate(lambda x, y: x*y, lambda x, y: x**y)
  59         assert f3(10, 11) == 10**11
  60         print '======== test delegate.__call__ with empty exception (empty)'
  61         f4 = delegate (emptyExcept=True)
  62         try:
  63                 f4 (3, 5)
  64         except RuntimeError, ex:
  65                 print 'Exception:', ex
  66         print '======== test delegate.__call__ with empty exception (not empty)'
  67         f4 += a
  68         f4 (3, 5)