A smart streaming program based on threads does not start in infinite recursion

I played with smart ways to create a python generator for the sequence A003602

This works, but I can’t understand why. It seems to me that this should hit infinite recursion. Is python a lazy evaluation somewhere that I won't recognize?

def N():
    i=1
    while True:
        yield i
        i+=1

def interleave(a,b):
    def result():
        x=a()
        y=b()
        while True:
            yield next(x)
            yield next(y)
    return result

def RZ():
    return interleave(N,RZ)()

gen=RZ()

It seems to me that since RZ instantly calls the method returned by the interlace, which in turn calls b, which is RZ (before the first call), it must be infinite recursion. But it really works. Can someone explain why?

+5
source share
3 answers

( yield) . , result() , , .

, x. , , , , . :

def test():
    yield 1
    a = test()
    while True:
        yield next(a)

a = test()
for i in range(10):
    print(next(a))

, . , , . , , yield 1, . N RZ - .

+4

, ( ). , , , , Python.

-, , ( , , N itertools.count(1)). , :

from itertools import count

def RZ():
    x=count(1)
    y=RZ()
    while True:
        yield next(x)
        yield next(y)

:

>>> gen = RZ()
>>> for i in range(1, 21):
    print i, next(gen)


1 1
2 1
3 2
4 1
5 3
6 2
7 4
8 1
9 5
10 3
11 6
12 2
13 7
14 4
15 8
16 1
17 9
18 5
19 10
20 3

, , . , python ( 2.7):

def getDepth(gen):
    depth = 0
    while gen:
        depth += 1
        gen = gen.gi_frame.f_locals.get("y")
    return depth

(, , ):

>>> for i in range(1, 21):
    print i, getDepth(gen), next(gen)

1 1 1
2 2 1
3 3 2
4 3 1
5 4 3
6 4 2
7 4 4
8 4 1
9 5 5
10 5 3
11 5 6
12 5 2
13 5 7
14 5 4
15 5 8
16 5 1
17 6 9
18 6 5
19 6 10
20 6 3

. , , N- , ceil(log(N, 2)) + 1.

Python ( ) 100 . , 2 ^ 99 + 1 (= 633,825,300,114,114,774,748,351,602,689). , .

+4

To me it seems like since RZ instantly calls the method returned by interleave which in turn calls b which is RZ (before the first call to yield), , yield , , RZ , , , RZ .

yield next(x) yield i , yield next(y) x = a(); y = b(); while True: yield next(x) , , , , , ...

count = 0
def N():
    i=1
    global count
    count += 1
    while True:
        yield i
        i+=1

def interleave(a,b):
    def result():
        global count
        count += 1
        x=a()
        y=b()
        while True:
            yield next(x)
            yield next(y)
    return result

def RZ():
    return interleave(N,RZ)()

gen = RZ() # 1) call RZ

gen = RZ()
r = [next(gen) for index in xrange(100)]
print count

14 , 100 , 20 1000, 28 10000, 34 100000, ...

+1
source

All Articles