是否可行,如果可行,是否可取,如果是,建议的方法是什么来装饰产生值的函数?
例如,考虑一下我编写的这个虚构的例子
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 :(得分:6)
生成器函数在调用时返回迭代器对象。如果你的装饰者本身也是一个生成器,你需要循环覆盖包裹的结果:
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
答案 1 :(得分:2)
为什么不仅仅产生实际存在的那些?而不是产生每个潜在的返回值?
def wrap(f, arg):
for x in f(arg):
yield x
(为清楚起见,省略了实际的装饰器语法,位置和关键字参数的处理等。)
答案 2 :(得分: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
答案 3 :(得分:0)
现有答案不处理产生并返回值的生成器。为此,您需要return (yield from f())
:
def dec(f):
def g():
return (yield from f())
return g
@dec
def f():
yield 'val'
return 'done'