无限“递归”的python程序

  如果一个函数直接或者间接调用了自己,那么就形成了递归(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,实现这个“无限递归”函数比较容易的。

 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 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:

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

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

https://segmentfault.com/q/1010000003059446

时间: 2024-10-14 18:38:34

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

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

目录 一.multiprocess模块 二.multiprocess.process模块 三.process模块介绍 3.1 方法介绍 3.2 属性介绍 3.3 在windows中使用process模块的注意事项 四.使用process模块创建进程 4.1 在Python中启动的第一个子进程 4.2 join方法 4.3 查看主进程和子进程的进程号 4.4 多个进程同时运行 4.5 多个进程同时运行,再谈join方法(1) 4.6 多个进程同时运行,再谈join方法(2) 4.7 通过继承Pro

110 python程序中的进程操作-开启多进程

之前我们已经了解了很多进程相关的理论知识,了解进程是什么应该不再困难了,刚刚我们已经了解了,运行中的程序就是一个进程.所有的进程都是通过它的父进程来创建的.因此,运行起来的python程序也是一个进程,那么我们也可以在程序中再创建进程.多个进程可以实现并发效果,也就是说,当我们的程序中存在多个进程的时候,在某些时候,就会让程序的执行速度变快.以我们之前所学的知识,并不能实现创建进程这个功能,所以我们就需要借助python中强大的模块. 一.multiprocess模块 仔细说来,multipro

编写高质量代码–改善python程序的建议(二)

原文发表在我的博客主页,转载请注明出处! 建议七:利用assert语句来发现问题断言(assert)在很多语言中都存在,它主要为调试程序服务,能够快速方便地检查程序的异常或者发现不恰当的输入等,可防止意想不到的情况出现.其语法如下: assert expression1 ["," expression2] 其中expression1的值会返回True或者False,当值为False的时候会引发AssertionError,而expression2是可选的,常用来传递具体的异常信息. 不

Python程序中应该尽量避免while True:的写法

最近在写python程序时,发现很多同事都尽量避免使用while循环而使用的是for循环,尤其是没用使用while Ture:的方式,while Ture:是无限循环的方式,我以前在写shell任务时经常使用,不过我一般注意使用了slepp 60来控制.其实这是一种很糟糕的风格,因为这样的循环通常复杂而难以理解,并且容易造成死循环,我们无论在写python程序还是shell程度时都应该尽量避免使用.

作为python程序员,你需要掌握这些技巧

本文和大家分享的是python开发必备的30 个小技巧,一起来看看吧,希望对大家学习和使用 python 语言有所帮助. 贴士#1. 原地交换两个数字 Python  提供了一个直观的在一行代码中赋值与交换(变量值)的方法,请参见下面的示例: x, y = 10, 20print(x, y) x, y = y, xprint(x, y) #1 (10, 20)#2 (20, 10) 赋值的右侧形成了一个新的元组,左侧立即解析(unpack )那个(未被引用的)元组到变量 和 . 一旦赋值完成,新

使用PyInstaller打包Python程序

使用PyInstaller打包Python程序 PyInstaller介绍: PyInstaller是一个能将Python程序转换成单个可执行文件的程序, 操作系统支持Windows, Linux, Mac OS X, Solaris和AIX.并且很多包都支持开箱即用,不依赖环境. 环境为windows7操作系统,python2.7.8 virtual environment 官网:https://github.com/pyinstaller/pyinstaller 详细步骤: 1. win7下

Python 程序员的 Golang 学习指南(III): 入门篇

基础语法 类型和关键字 类型 // 基础类型 布尔类型: bool 整型: int8,uint8,int16,uint16,int32,uint32,int64,uint64,int,rune,byte,complex128, complex64,其中,byte 是 int8 的别名 浮点类型: float32 . float64 复数类型: complex64 . complex128 字符串: string 字符类型: rune(int32的别名) 错误类型: error // 复合类型 指

Python程序员的发展前景是怎样的?

Python程序员的发展前景是怎样的? 随着Python的技术的流行, Python在为人们带来工作与生活上的便捷后,关注者们开始慢慢关心Python的发展前景与方向. 从自身特性看Python发展 Python自身强大的优势决定其不可限量的发展前景.Python作为一种通用语言,几乎可以用在任何领域和场合,角色几乎是无限的.Python具有简单.易学.免费.开源.可移植.可扩展.可嵌入.面向对象等优点,它的面向对象甚至比java和C#.net更彻底. 它是一种很灵活的语言,能帮你轻松完成编程工

月薪3万的python程序员都看了这本书

想必大家都看过吧 Python编程从入门到实践 全书共有20章,书中的简介如下: 本书旨在让你尽快学会 Python ,以便能够编写能正确运行的程序 —— 游戏.数据可视化和 Web 应用程序,同时掌握让你终身受益的基本编程知识.本书适合任何年龄的读者阅读,它不要求你有任何 Python 编程经验,甚至不要求你有编程经验.如果你想快速掌握基本的编程知识以便专注于开发感兴趣的项目,并想通过解决有意义的问题来检查你对新学概念的理解程度,那么本书就是为你编写的.本书还可供初中和高中教师用来通过开发项目