Use a decorator to turn a function into a generator in Python -
is there way decorator convert function below generator?
@decorator_that_makes_func_into_generator def countdown(n): while n > 0: print n, n = n - 1
the function can modified if necessary. note function not have yield statement, otherwise generator.
if can't change source of countdown
, you'll have capture output:
import sys io import stringio def decorator_that_makes_func_into_generator(func): def wrapper(*a, **ka): # temporarily redirect output stringio instance (intr) ts, intr = sys.stdout, stringio() sys.stdout = intr func(*a, **ka) # restore normal stdout backup (ts) sys.stdout = ts # output intr, split whitespace , use generator yield intr.getvalue().split() return wrapper @decorator_that_makes_func_into_generator def countdown(n): while n > 0: print(n) n = n - 1 print(countdown(5), list(countdown(5))) # <generator object wrapper @ 0x01e09058> ['5', '4', '3', '2', '1']
if can change function , if want return countdown
(list
or other sequence type) , then create generator returned object, decorator'd like
def decorator_that_makes_func_into_generator(func): def wrapper(*a, **ka): yield func(*a, **ka) return wrapper
note: awesome yield from
introduced in python 3.3, on older versions use plain loop instead:
for x in func(*a, **ka): yield x
example:
@decorator_that_makes_func_into_generator def countdown(n): res = [] while n > 0: res.append(n) n = n - 1 return res print(type(countdown(5)), list(countdown(5))) # output: <class 'generator'> [5, 4, 3, 2, 1]
nothing stops applying decorator_that_makes_func_into_generator
generator:
@decorator_that_makes_func_into_generator def countdown(n): while n > 0: yield n n = n - 1 print(type(countdown(5)), list(countdown(5))) # outputs <class 'generator'> [5, 4, 3, 2, 1]
Comments
Post a Comment