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

def fib(n):
if n <= 2:
return 1
else:
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,实现这个“无限递归”函数比较容易的。

 from greenlet import greenlet
def test1():
while True:
z = gr2.switch('msg from test1')
print('test1 ', z) def test2(v):
while True:
u = gr1.switch('msg from test2')
print('test2 ', u) if __name__ == '__main__':
gr1 = greenlet(test1)
gr2 = greenlet(test2)
print gr1.switch()
   接下来用generator来模拟这个实现
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 @consumer
def test1():
while True:
data = yield
print('test1 ', data)
gr2.send('msg from test1') @consumer
def test2():
while True:
data = yield
print('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:
 

无限“递归”的python程序的更多相关文章

  1. 在Python程序中的进程操作,multiprocess.Process模块

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

  2. python 全栈开发,Day38(在python程序中的进程操作,multiprocess.Process模块)

    昨日内容回顾 操作系统纸带打孔计算机批处理 —— 磁带 联机 脱机多道操作系统 —— 极大的提高了CPU的利用率 在计算机中 可以有超过一个进程 进程遇到IO的时候 切换给另外的进程使用CPU 数据隔 ...

  3. Python程序中的进程操作-开启多进程(multiprocess.process)

    目录 一.multiprocess模块 二.multiprocess.process模块 三.process模块介绍 3.1 方法介绍 3.2 属性介绍 3.3 在windows中使用process模 ...

  4. 29、Python程序中的进程操作(multiprocess.process)

    一.multiprocess模块 multiprocess不是一个模块而是python中一个操作.管理进程的包. 子模块分为四个部分: 创建进程部分 进程同步部分 进程池部分 进程之间数据共享 二.m ...

  5. Python程序中的进程操作--—--开启多进程

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

  6. 编写高质量Python程序(四)库

    本系列文章为<编写高质量代码--改善Python程序的91个建议>的精华汇总. 按需选择 sort() 或者 sorted() Python 中常用的排序函数有 sort() 和 sort ...

  7. Python程序员的进化史

    各种程序员所写的阶乘算法代码 # -*- coding: utf-8 -*- #新手程序员(递归) def factorial(x): if x == 0: return 1 else: return ...

  8. 编写高质量代码--改善python程序的建议(八)

    原文发表在我的博客主页,转载请注明出处! 建议四十一:一般情况下使用ElementTree解析XML python中解析XML文件最广为人知的两个模块是xml.dom.minidom和xml.sax, ...

  9. 无限递归的构造器和javap使用指南

    无限递归的构造器和javap使用指南 public class ConstructorRecursion { ConstructorRecursion rc; { rc = newConstructo ...

随机推荐

  1. [数据结构]Treap简介

    [写在前面的话] 如果想学Treap,请先了解BST和BST的旋转 二叉搜索树(BST)(百度百科):[here] 英文好的读者可以戳这里(维基百科) 自己的博客:关于旋转(很水,顶多就算是了解怎么旋 ...

  2. JQuery使用和选择器

    1.优点 (1)能解决浏览器的兼容性JS问题 (2)解决JS代码冗余的问题 (3)动画效果更容易实现 2.压缩过的和不压缩的区别 (1)开发过程中用未压缩的:上线后用压缩版本. (2)版本问题:1.X ...

  3. JDBC 数据库连接池

    http://www.cnblogs.com/lihuiyy/archive/2012/02/14/2351768.html JDBC 数据库连接池 小结   当对数据库的访问不是很频繁时,可以在每次 ...

  4. (简单) POJ 3126 Prime Path,BFS。

    Description The ministers of the cabinet were quite upset by the message from the Chief of Security ...

  5. phpcms v9 后台首页 去掉团队信息等版权

    phpcms\languages\zh-cn\admin.lang.php $LANG['main_product_team'] = 'PHPCMS开发团队'; phpcms\modules\admi ...

  6. HDU 5621 KK's Point

    N个点中任意选取四个点,就能产生一个圆内的交点,所以圆内总共有C(N,4)个交点,圆上有N个,相加就可以了. 注意:组合数运算的时候会爆longlong,中间先除一下就可以了. #include &l ...

  7. Android L(5.0)源码之手势识别GestureDetector

    本人新手,最近下了Android L的源码,正在研究手势识别,能力有限,现总结如下: Android识别触摸屏手势使得用户体验大大提高.在View类中有个View.OnTouchListener内部接 ...

  8. 学习wcf

    链接请看下面 第一部分:http://boytnt.blog.51cto.com/966121/796884 第二部分:http://boytnt.blog.51cto.com/966121/7969 ...

  9. zeromq随笔

    ZMQ (以下 ZeroMQ 简称 ZMQ)是一个简单好用的传输层,像框架一样的一个 socket library,他使得 Socket 编程更加简单.简洁和性能更高.是一个消息处理队列库,可在多个线 ...

  10. 一个异步任务接收两个url下载两个图片

    有两个url,一个是下载用户头像的url,一个是下载用户上传图片的url,想要用一个异步任务同时下载这两个图片. 程序的下载任务是这么执行的,先接受url参数,然后调用 imgUrls = infoP ...