如果一個函數(shù)直接或者間接調(diào)用了自己,那么就形成了遞歸(recursion),比如斐波那契數(shù)列的一個實現(xiàn)

def fib(n):    if n <= 2:        return 1    else:        return fib(n - 1) + fib(n - 2)

  遞歸一定要有結(jié)束條件,否則就形成了死循環(huán), 比如下面的例子:

大學(xué)生就業(yè)培訓(xùn),高中生培訓(xùn),在職人員轉(zhuǎn)行培訓(xùn),企業(yè)團訓(xùn)

def a():
    b()def b():
    a() 
if __name__ == '__main__':
    a()

大學(xué)生就業(yè)培訓(xùn),高中生培訓(xùn),在職人員轉(zhuǎn)行培訓(xùn),企業(yè)團訓(xùn)

  很快 就會拋出一個異常:RuntimeError: maximum recursion depth exceeded

  會什么報這個異常,很簡單,我們都知道子程序調(diào)用(call)需要壓棧出棧,如果無限遞歸調(diào)用,那么就一直壓棧,沒有出棧,內(nèi)存消耗也越來愈多。python比較高級,直接拋出這個異常,結(jié)束程序運行。

 

  前面的文章提到協(xié)程(coroutine)這個概念,不管是generator還是greenlet,語法看起來都很像函數(shù)調(diào)用,但事實上并不是,協(xié)程只是在切換的時候把當前調(diào)用棧中的信息存儲了起來:

“all local state is retained, including the current bindings of local variables, the instruction pointer, and the internal evaluation stack. When the execution is resumed by calling one of the generator’s methods, the function can proceed exactly as if the yield expression was just another external call.”

 

  利用協(xié)程實現(xiàn)無限遞歸似乎成為了可能, 維基百科上有偽代碼描述。首先對于greenlet,實現(xiàn)這個“無限遞歸”函數(shù)比較容易的。

大學(xué)生就業(yè)培訓(xùn),高中生培訓(xùn),在職人員轉(zhuǎn)行培訓(xùn),企業(yè)團訓(xùn)

 1 from greenlet import greenlet 2 def test1(): 3     while True: 4         z = gr2.switch('msg from test1') 5         print('test1 ', z) 6  7 def test2(v): 8     while True: 9         u = gr1.switch('msg from test2')10         print('test2 ', u)11 12 if __name__ == '__main__':13     gr1 = greenlet(test1)14     gr2 = greenlet(test2)15     print gr1.switch()

大學(xué)生就業(yè)培訓(xùn),高中生培訓(xùn),在職人員轉(zhuǎn)行培訓(xùn),企業(yè)團訓(xùn)

 

   接下來用generator來模擬這個實現(xiàn)

大學(xué)生就業(yè)培訓(xùn),高中生培訓(xùn),在職人員轉(zhuǎn)行培訓(xùn),企業(yè)團訓(xùn)

def consumer(func):    def wrapper(*args,**kw):
        gen = func(*args, **kw)
        gen.next()        return gen
    wrapper.__name__ = func.__name__
    wrapper.__dict__ = func.__dict__
    wrapper.__doc__  = func.__doc__
    return wrapper

@consumerdef test1():    while True:
        data = yield
        print('test1 ', data)
        gr2.send('msg from test1')

@consumerdef test2():    while True:
        data = yield
        print('test2 ', data)
        gr1.send('msg from test2')

gr1 = test1()
gr2 = test2()

gr1.send("init")

大學(xué)生就業(yè)培訓(xùn),高中生培訓(xùn),在職人員轉(zhuǎn)行培訓(xùn),企業(yè)團訓(xùn)

 

運行報錯:ValueError: generator already executing,這個錯誤在這篇文章也有提到,這個問題,在維基百科上正確的姿勢。我們改改代碼

 

大學(xué)生就業(yè)培訓(xùn),高中生培訓(xùn),在職人員轉(zhuǎn)行培訓(xùn),企業(yè)團訓(xùn)

def test1():    while True:    
        data = yield (gr2, 'msg from test1')        print('test1 ', data)        
def test2():    while True:
        
        data = yield (gr1, 'msg from test2')        print('test2 ', data)
        
gr1 = test1()
gr2 = test2()
gr1.next()
gr2.next()def run():
    co, data = gr1, 'init'
    while True:
        co, data = co.send(data)
run()

大學(xué)生就業(yè)培訓(xùn),高中生培訓(xùn),在職人員轉(zhuǎn)行培訓(xùn),企業(yè)團訓(xùn)

This‘s Ok!

 

references:

http://www.cnblogs.com/xybaby/p/6323358.html

https://en.wikipedia.org/wiki/Coroutine#Implementations_for_Python

https://segmentfault.com/q/1010000003059446

 

本文版權(quán)歸作者xybaby(博文地址:http://www.cnblogs.com/xybaby/)所有,歡迎轉(zhuǎn)載和商用,請在文章頁面明顯位置給出原文鏈接并保留此段聲明,否則保留追究法律責(zé)任的權(quán)利,其他事項,可留言咨詢。

http://www.cnblogs.com/xybaby/p/6343285.html