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

кажется усложненной. Что конкретно вы подразумеваете под «украшением функции, которая дает значение»? Какой прецедент вы имеете в виду? –

+0

Случай использования @ivan_pozdeev: у меня есть куча функций генератора, которые дают новые значения из api. Я хочу применять фильтры, не касаясь существующей функции. Итак, для примера с разделителем exfaple 'def get_new(): result = new_result(); результат результата «Я хочу только отфильтровать и уронить, скажем, результаты, которые содержат строку« foobar », не сбрасывая сложные процессы« new_result » – yayu

ответ

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

Смежные вопросы