如果一个函数直接或者间接调用了自己,那么就形成了递归(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. CodeForces 605A Sorting Railway Cars

    求一下最长数字连续上升的子序列长度,n-长度就是答案 O(n)可以出解,dp[i]=dp[i-1]+1,然后找到dp数组最大的值. #include<cstdio> #include< ...

  2. 理解MySQL——索引与优化(转)

    转自:http://www.cnblogs.com/hustcat/archive/2009/10/28/1591648.html 写在前面:索引对查询的速度有着至关重要的影响,理解索引也是进行数据库 ...

  3. js删除最后一个字符串方法

    JS 删除字符串最后一个字符的几种方法 2010-12-02 08:18:35|  分类: 编程 |举报 |字号 订阅   字符串:string s = "1,2,3,4,5," ...

  4. maven bundle

    今天引入了几个bundle到pom,尽然说missing,我还以为是nexus组织下载.把type=bundle去掉可以下载,后来同事给了我这个连接https://issues.apache.org/ ...

  5. CodeForces 620B Grandfather Dovlet’s calculator

    水题 #include<cstdio> #include<cstring> #include<cmath> #include<stack> #inclu ...

  6. AnsiString用法(转)

    源:AnsiString用法 //Ansistring 转 char void __fastcall TForm1::Button1Click(TObject *Sender) { AnsiStrin ...

  7. Android线程之Thread 、Runnable 的两个例子

    Thread例子: package fy.test; import android.app.Activity; import android.os.Bundle; import android.os. ...

  8. Servlet中的过滤器Filter用法

    1.过滤器的概念 Java中的Filter 并不是一个标准的Servlet ,它不能处理用户请求,也不能对客户端生成响应. 主要用于对HttpServletRequest 进行预处理,也可以对Http ...

  9. Session监听事件的处理

    设置Session监听  在web.xml文件中: <listener> <listener-class>cjq.login.listener.UpdateLogOutTime ...

  10. jquery遍历二维数组

    function eachTowArray() {  var ar = [[1,2,3],[4,5,6],[7,8,9]];  var result="";   //结果存放变量  ...