2015-11-05 78 views
1

我在Python 3中實現了一個Delegate類,它在對象實例中封裝了一個函數對象。可以在一個代理上註冊多個函數對象(使用.NET術語,這是一個MultiCastDelegate)。假定所有註冊的函數都接受相同的參數,可以調用委託並一次調用所有函數。如何爲我的Delegate類實現迭代器或生成器?

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__()方法應該返回由所述功能對象和返回值的元組。

我試過到目前爲止:

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

我對此並不熟悉,但我給了它一個鏡頭。它沒有很好的測試,但它會幫助你解決你的任務。下面是代碼:

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 
相關問題