2014-11-23 70 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