如果一个函数直接或者间接调用了自己,那么就形成了递归(recursion),比如斐波那契数列的一个实现

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

  递归一定要有结束条件,否则就形成了死循环, 比如下面的例子:

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

很快 就会抛出一个异常:RuntimeError: maximum recursion depth exceeded
会什么报这个异常,很简单,我们都知道子程序调用(call)需要压栈出栈,如果无限递归调用,那么就一直压栈,没有出栈,内存消耗也越来愈多。python比较高级,直接抛出这个异常,结束程序运行。
前面的文章提到协程(coroutine)这个概念,不管是generator还是greenlet,语法看起来都很像函数调用,但事实上并不是,协程只是在切换的时候把当前调用栈中的信息存储了起来:

“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.”

  利用协程实现无限递归似乎成为了可能, 维基百科上有伪代码描述。首先对于greenlet,实现这个“无限递归”函数比较容易的。

 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()

接下来用generator来模拟这个实现
def consumer(func):def wrapper(*args,**kw):gen = func(*args, **kw)gen.next()return genwrapper.__name__ = func.__name__wrapper.__dict__ = func.__dict__wrapper.__doc__  = func.__doc__return wrapper@consumer
def test1():while True:data = yieldprint('test1 ', data)gr2.send('msg from test1')@consumer
def test2():while True:data = yieldprint('test2 ', data)gr1.send('msg from test2')gr1 = test1()
gr2 = test2()gr1.send("init")

运行报错:ValueError: generator already executing,这个错误在这篇文章也有提到,这个问题,在维基百科上正确的姿势。我们改改代码

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()

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

无限“递归”的python程序相关推荐

  1. 运行python脚本卡住_为什么我的 Python 程序卡住啦!

    原标题:为什么我的 Python 程序卡住啦! 文 | xybaby出处 | cnblogs 服务器程序员最怕的就是程序crash,不过有时候程序没有crash,但是"不工作"了也 ...

  2. python运行程序为什么会卡住_为什么我的 Python 程序卡住啦!

    本文简答介绍在linux环境下如何利用gdb来分析卡住的程序,本文使用的Python为Cpython2.7,操作系统为Debian. 阻塞在IO 程序被卡住,很可能是程序被阻塞了,即在等待(wait) ...

  3. Python maximum recursion depth exceeded while calling a Python object (gevent的SSL无限递归错误)的问题解决

    报错信息 源码位置 分析 很尴尬,完全看不出原因导致这个报错 解决方法 通过删除代码的方式一部一部删除,找到了问题出处 原因是包的顺序出现了问题,把位置互换一下,发现没有报错了,但是很明确的告诉你这两 ...

  4. Python程序控制结构(二)循环结构:for in遍历循环,while无限循环,循环+else

    Python程序控制结构(二)循环结构: 1. for in遍历循环 2. while无限循环 一.遍历循环 二.遍历循环的应用 遍历循环是使用for in保留字形成的一种循环,它能够对遍历结构中的每 ...

  5. 在Python程序中设置函数最大递归深度

    在函数调用时,为了保证能够正确返回,必须进行保存现场和恢复现场,也就是被调函数结束后能够回到主调函数中离开时的位置然后继续执行主调函数中的代码.这些现场或上下文信息保存在线程栈中,而线程栈的大小是有限 ...

  6. python递归查找_Python程序使用递归查找数字的幂

    python递归查找 Given the base x and the power y and we have to find the x to the power y using recursion ...

  7. python setattr无限递归_如何避免使用setattr和属性setter来避免递归循环?

    在调用setattr时,当试图设置某个带有setter的属性的值时,这将导致无限递归循环:class TypeSystem(object): def __setattr__(self, key, va ...

  8. 在python程序中的进程操作

    ********在python程序中的进程操作********之前我们已经了解了很多进程相关的理论知识,了解进程是什么应该不再困难了,刚刚我们已经了解了, 运行中的程序就是一个进程.所有的进程都是通过 ...

  9. python在中小学教学中的应用-在python程序中的进程操作

    ********在python程序中的进程操作********之前我们已经了解了很多进程相关的理论知识,了解进程是什么应该不再困难了,刚刚我们已经了解了, 运行中的程序就是一个进程.所有的进程都是通过 ...

最新文章

  1. java语言用什么编程_使用什么编程语言开发Java?
  2. 2021年加拿大工程院院士名单出炉,杨强、张大鹏、刘学等多位华人入选
  3. LFS6.2搭建笔记(一)
  4. 自己写getElementsByClass()方法
  5. 一个能极大提高生产率的Chrome新建标签页扩展
  6. 您可能不需要翻译您JavaScript
  7. Linux 配置网络
  8. MathType 的使用
  9. JS无限弹窗代码实现
  10. 软件测试工具都有哪些
  11. 现代雷达系统分析与设计---数字中频正交采样
  12. csgo如何增加人机数量及平衡_csgo怎么单机跟电脑打?怎么增加BOT?
  13. 行测:判断推理之图形推理
  14. 【笔记 - linux基础入门 01】基本概念及操作
  15. leetcode 周赛214 学习笔记(5561、1647)
  16. 9章 RxJava混合实战
  17. Android多人视频聊天应用的开发(一)快速集成
  18. 《走出软件作坊》开始预订
  19. BT服务器架设全攻略
  20. docker制作nginx+nginx-module-vts镜像基于alpine镜像

热门文章

  1. 【caffe-Windows】微软官方caffe之 matlab接口配置
  2. 李宏毅机器学习课程12~~~半监督学习
  3. python安装redis库
  4. win7rc 序列号- 10/21之前
  5. 反射笔记-----------------------------
  6. 利用反射修改final数据域
  7. (WPF) DataGrid之绑定
  8. Linux技巧:一次删除一百万个文件最快方法
  9. 无刷新上传Excel后利用JQuery AJAX 显示进度条的实现方式
  10. Angular自学笔记(?)DI提供者