如何用python装饰生成器
因此,我定义了一个简单的生成器:如何用python装饰生成器,python,generator,decorator,Python,Generator,Decorator,因此,我定义了一个简单的生成器: def gen1(x): if x <= 10: yield x for v in gen1(x + 1): yield v 现在,如果我重新定义gen1 @dec def gen1(x): ... for i in gen1(1): print i # Nothing printed 但如果我使用: some_gen = dec(gen1) for i in s
def gen1(x):
if x <= 10:
yield x
for v in gen1(x + 1):
yield v
现在,如果我重新定义gen1
@dec
def gen1(x):
...
for i in gen1(1):
print i # Nothing printed
但如果我使用:
some_gen = dec(gen1)
for i in some_gen(1):
print i # Prints 1 to 9, as needed
为什么我的decorator不工作以及如何修复它?您的
gen1
的递归调用也取决于您的decorator,因此所有内容都会被decorator消耗掉
最简单的修复方法是以非递归样式编写生成器,或者封装递归:
封装:
由于装饰器和递归之间的交互,它无法工作。因为生成器是递归的,所以它依赖于某种递归关系。通过在生成器和子生成器之间注入修改修饰符,可以打破这种重复关系 只要
@dec
删除最后一个元素,就无法通过单独更改@dec
使其与gen1()兼容
但是,您可以更改gen1()
,使其与@dec
兼容:
def dec(gen):
def new_gen(x):
g = gen(x)
value = g.next()
for v in g:
yield value
value = v
return new_gen
@dec
def gen1(x):
def gen2(x):
if x <= 10:
yield x
for v in gen2(x + 1):
yield v
for v in gen2(x):
yield v
for i in gen1(1):
print i # Prints 1 to 9, as needed
def dec(gen):
def新版本(x):
g=发电机(x)
值=g.next()
对于v in g:
收益率
值=v
返回新的_gen
@十二月
def gen1(x):
def gen2(x):
如果x我的解决方案是在发电机的顶部创建一个发电机!这实际上是一个装饰电话的想法。你也是
def funca():
while True:
print "in funca"
yield True
def dec(func):
while True:
print "in funcb"
func.next()
yield True
decfa = dec(funca())
decfa.next()
>>
"in funcb"
"in funca"
至于你的问题(只产生最后一个值),我会这样做:
def funca():
for i in range(1,5):
yield i
def dec2(ff):
try:
while True:
val=ff.next()
except:
yield val
>>>dec2(funca()).next()
4
所以我不能修饰递归函数?另外,为什么gen1=dec(gen1)不能工作?gen1=dec(gen1)
与@dec def gen1():…
相同。它重新绑定gen1
,而不是创建新名称。请参阅我关于递归的更新答案。
def dec(gen):
def new_gen(x):
g = gen(x)
value = g.next()
for v in g:
yield value
value = v
return new_gen
@dec
def gen1(x):
def gen2(x):
if x <= 10:
yield x
for v in gen2(x + 1):
yield v
for v in gen2(x):
yield v
for i in gen1(1):
print i # Prints 1 to 9, as needed
def funca():
while True:
print "in funca"
yield True
def dec(func):
while True:
print "in funcb"
func.next()
yield True
decfa = dec(funca())
decfa.next()
>>
"in funcb"
"in funca"
def funca():
for i in range(1,5):
yield i
def dec2(ff):
try:
while True:
val=ff.next()
except:
yield val
>>>dec2(funca()).next()
4