A decorating function that gives

Is it possible, and if so, appropriate, and if so, what would be the recommended method for decorating a function that gives a value?

For example, consider this imaginary example I made

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

      

+3


source to share


3 answers


A generator function, when called, returns an iterator object. If your decorator is itself a generator, you need to loop over the resulting result:

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

      



If you are using Python 3.3 or higher, you can use delegation to control the wrapped generator using yield from

:

if flag:
    yield from gen

      

+5


source


Rather than fetching every potential return value, why not yield to only those that actually exist? Something like

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

      



(The actual decorator syntax, positional and keyword handling, etc. are omitted for clarity.)

+2


source


In the case of comment42684128, the solution is as simple as:

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

      

As a decorator:

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

      

+2


source







All Articles