2014-11-23 54 views
3

是否有可能,如果是這樣,建議,如果是這樣,那麼裝飾產生價值的函數的推薦方法是什麼?裝飾函數產生

例如,考慮這個假想例子我由

def foobar_creator(func): 
    def wrapped(**kwargs): 
     res = func(**kwargs) 
     flag = True 
     for k,v in kwargs: 
      if res % v == 0: 
       flag = False 
       yield k 
     if flag: 
      yield res 
    return wrapped 

@foobar_creator 
def generic_yielder(**kwargs): 
    for i in xrange(sys.maxint): 
      yield i 

for i in generic_yielder(foo=3, bar=5, foobar=15): 
     print i 
+0

看起來過於複雜。 「裝飾能產生價值的功能」的意思是什麼?你有什麼用例? – 2014-11-23 10:35:05

+0

@ivan_pozdeev用例:我有一堆發生器函數可以從api產生新的值。我想應用過濾器而不觸及現有的功能。所以對於一個精簡的例子'def get_new():result = new_result(); yield result'我想過濾掉並只產出,說包含字符串'foobar'的結果,而不會破壞複雜的'new_result'進程 – yayu 2014-11-23 11:03:55

回答

5

發電機功能被調用時,則返回一個迭代器對象。如果你的裝飾本身就是一個發電機也一樣,你需要循環在包裹結果:

def foobar_creator(func): 
    def wrapped(**kwargs): 
     gen = func(**kwargs) 
     flag = True 
     for k, v in kwargs: 
      if res % v == 0: 
       flag = False 
       yield k 
     if flag: 
      for res in gen: 
       yield res 
    return wrapped 

如果您正在使用Python 3.3或者,你可以使用代表團手控制發電機包裹通過使用yield from

if flag: 
    yield from gen 
2

而不是屈服每潛在返回值,爲什麼不產生只有那些實際上存在嗎?喜歡的東西

def wrap(f, arg): 
    for x in f(arg): 
     yield x 

(實際修飾語法,的位置和關鍵字參數處理等是爲了清楚省略了。)

2

對於comment42684128的情況下,該解決方案是簡單:

(v for v in f(<args>) if filter_condition(v)) 

作爲裝飾:

def yfilter(filter_condition): 
    def yfilter_p(f): 
     def wrapped(*args,**kwargs): 
      return (v for v in f(*args,**kwargs) if filter_condition(v)) 
     return wrapped 
    return yfilter_p 
+0

謝謝,這很好。 – yayu 2014-11-25 15:59:36