如何为Delegate类实现迭代器或生成器?

时间:2015-11-05 17:45:28

标签: python-3.x delegates iterator generator

我在Python 3中实现了一个Delegate类,它将一个函数对象包装在一个对象实例中。可以在一个代理上注册多个功能对象(在.NET术语中它是MultiCastDelegate)。假设所有注册函数都接受相同的参数,则可以调用委托并立即调用所有函数。

Delegate实施:

class Delegate:
  def __init__(self, *funcs):
    self.__invocationList__ = []
    for func in funcs:
      self.__invocationList__.append(func)

  def __iadd__(self, func):
    self.__invocationList__.append(func)
    return self

  def __isub__(self, func):
    self.__invocationList__.remove(func)
    return self

  def __call__(self, *args, **kwargs):
    if (len(self.__invocationList__) == 1):
      return self.__invocationList__[0](*args, **kwargs)
    else:
      res = {}
      for func in self.__invocationList__:
        res[func] = func(*args, **kwargs)
      return res

  @property
  def isMulticast(self):
    return (len(self.__invocationList__) > 1)

用法示例:

def test1():
  return 5
def test2(a, b):
  return a + b
def test3(a, b):
  return a * b + 15

delegate = Delegate(test1)
result = delegate()
print("test1: {0}".format(result))

delegate = Delegate(test2)
result = delegate(3, 8)
print("test2: {0}".format(result))

delegate += test3
results = delegate(2, 9)
print("test2: {0}".format(results[test2]))
print("test3: {0}".format(results[test3]))

我想在这个类上实现迭代器或生成器,因此可以在for循环中使用委托。

它看起来怎么样?

# loop over every result from delegate, call with parameters 4 and 18
for result in delegate(4, 18):
  print("function={0}  result={1}".format(*result))

迭代器__next__()方法应该返回一个由function-object和return值组成的元组。

到目前为止我尝试了什么:

class Delegate:
  # ...
  # see code from above

  def __iter__(self):
    print("Delegate.__iter__():")

    class iter:
      def __init__(self2, *args, **kwargs):
        print(str(args))
        self2.__args =    args
        self2.__kwargs =  kwargs
        self2.__index = 0

      def __iter__(self2):
        return self2

      def __next__(self2):
        if (self2.__index == len(self.__invocationList__)):
          raise StopIteration
        func = self.__invocationList__[self2.__index]
        self2.__index += 1
        return func(*self2.__args, **self2.__kwargs)

    return iter()

因为构造函数方法已经由Delegate创建本身使用,所以我将迭代器实现为嵌套类。但不幸的是,我无法将调用参数* args和** kwargs传递给迭代器。

所以我的问题:

  • 为代表实现迭代器/生成器模式是否可行且明智?
  • 我应该改变什么才能让它发挥作用?

我只是尝试实现迭代器模式。如果它有效,我想将其升级为发电机 - 如果可能的话:):

1 个答案:

答案 0 :(得分:1)

我对此并不熟悉,但我试了一下。它没有经过充分测试,但它可以帮助您解决任务。这是代码:

class Delegate:
  class IterDelegate:
    def __init__(this, invocationList, *args, **kwargs):
      this.__args = args
      this.__kwargs = kwargs
      this._invocationList = invocationList

    def __iter__(this):
      this.__index = 0
      return this

    def __next__(this):
      if this.__index < len(this._invocationList):
        func = this._invocationList[this.__index]
        this.__index += 1
        return (func.__name__, func(*this.__args, **this.__kwargs))
      raise StopIteration

  def __init__(self, func):
    if (type(func) == 'list'):
      self._invocationList = func
    else:
      self._invocationList = [func]

  def __call__(self, *args, **kwargs):
    return self.IterDelegate(self._invocationList, *args, **kwargs)

  def __iadd__(self, func):
    self._invocationList.append(func)
    return self

  def __isub__(self, func):
    self._invocationList.remove(func)
    return self


def test2(a, b):
  return a + b

def test1(*args):
  return 6

delegate = Delegate(test2)

delegate += test1

results = delegate(2,3)

for r in results:
  print("function={0}  result={1}".format(*r))

这将给出结果

function=test2  result=5
function=test1  result=6