如果一个函数直接或者间接调用了自己,那么就形成了递归(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. 17.4.3 使用MulticastSocket实现多点广播(2)

    // 让该类实现Runnable接口,该类的实例可作为线程的target public class MulticastSocketTest implements Runnable { // 使用常量作 ...

  2. iOS 图片拉伸

    UIImage *img = [UIImage imageNamed:@"CGUnwrapRed_2"]; img = [img stretchableImageWithLeftC ...

  3. Git GitHub的使用

    Git的工作区示意 GIT总结 使用git github也一段时间突然发现还是少了一些总结,那就从这儿开始吧! (1)git的配置,这儿就从单独的安装配置开始 安装:sudo yum install ...

  4. iOS 添加手机密码、指纹进行安全验证

    为APP添加安全验证 1.导入头文件 #import <LocalAuthentication/LocalAuthentication.h> 2.添加手机密码验证 //创建安全验证对象 L ...

  5. dsp与dmp的cookie mapping

    dsp   ad.com   在  meijiu.com上部署广告. 假设dmp叫cm.api.taobao.com 建立gid映射表 (1) ad.com在meiju.com的页面上部署,指向dmp ...

  6. ucos互斥信号量解决优先级反转问题

    在可剥夺性的内核中,当任务以独占方式使用共享资源的时候,会出现低优先级任务高于高优先级任务运行的情况,这种情况叫做优先级反转,对于实时操作系统而言,这是一场灾难,下面我们来说说优先级反转的典型环境. ...

  7. 利用jackson转成json字符串(ssh中)

    public String getJsonString(Object o){ ObjectMapper om = new ObjectMapper(); StringWriter sw = new S ...

  8. ireport 取消自动分页,detail不分页,当没有数据的时候显示title

    报表文件属性页面 lgnore pagination 勾选上,就可以取消分页功能.

  9. A股暴跌三日市值蒸发4.2万亿 股民人均浮亏超2万

    A股暴跌三日市值蒸发4.2万亿 股民人均浮亏超2万 http://finance.qq.com/a/20150508/010324.htm?pgv_ref=aio2015&ptlang=205 ...

  10. UVa 10176 - Ocean Deep ! - Make it shallow !!

    题目大意:判断一个很大的二进制能否被131071整除.在二进制转十进制的过程中不断取模,最后判断结果是否是0就可以了. #include <cstdio> #include <cst ...