15

そこで、単純なジェネレーターを定義しました。

def gen1(x):
    if x <= 10:
        yield x
        for v in gen1(x + 1):
            yield v

基本的に、すべての値を返すように装飾したいのですが、最後は:

def dec(gen):

    def new_gen(x):
        g = gen(x)
        value = g.next()
        for v in g:
            yield value
            value = v

    return new_gen

さて、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

デコレータが機能しないのはなぜですか?どうすれば修正できますか?

4

4 に答える 4

8

あなたの再帰呼び出しgen1もデコレーターの影響を受けるため、すべてがデコレーターによって消費されます。

最も簡単な修正は、ジェネレーターを非再帰スタイルで記述するか、再帰をカプセル化することです。

カプセル化:

@dec
def gen1(x):
    def inner(x):
        if x <= 10:
            yield x
            for v in inner(x + 1):
                yield v
    return inner(x)

非再帰:

@dec
def gen1(x):
    for v in range(x, 11):
        yield v
于 2012-12-17T13:33:18.587 に答える
1

デコレータと再帰の間の相互作用のために機能しません。ジェネレーターは再帰的であるため、特定の再帰関係に依存しています。ジェネレーターとサブジェネレーターの間に変更デコレーターを挿入することで、その繰り返し関係を壊しています。

最後の要素を落とす限り、変更だけ@decでは対応できません。gen1()@dec

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

ここでの秘訣は、gen1()非再帰を作成し、すべての作業を別の装飾されていないジェネレーターに委譲することです。後者は再帰的にすることができます。

于 2012-12-17T13:33:55.737 に答える
0

そのように sth を実行しなければならなかったときの私の解決策は、ジェネレーターの上にジェネレーターを作成することでした! これは、実際には装飾された呼び出しのアイデアです。そうしたらいい、

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
于 2014-09-16T12:58:35.167 に答える