無限“遞歸”的python程序

  如果一個函數直接或者間接調用了自己,那么就形成了遞歸(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

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/259675.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/259675.shtml
英文地址,請注明出處:http://en.pswp.cn/news/259675.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

java slf4j_SLF4J 使用手冊

原文鏈接 譯者&#xff1a;zivyuJava的簡單日志門面( Simple Logging Facade for Java SLF4J)作為一個簡單的門面或抽象&#xff0c;用來服務于各種各樣的日志框架&#xff0c;比如java.util.logging、logback和log4j。SLF4J允許最終用戶在部署時集成自己想要的日志框架。需要…

[譯]Java 垃圾回收介紹

說明&#xff1a;這篇文章來翻譯來自于Javapapers 的Java Garbage Collection Introduction 在Java中&#xff0c;對象內存空間的分配與回收是由JVM中的垃圾回收進程自動完成的。和C語言不一樣的是&#xff0c;開發中不需要在Java中寫垃圾回收代碼。這也是使Java更加流行而且幫…

打印三角形

直角三角形 #include<iostream> using namespace std; int main() { int i,j; for(i1;i<10;i) {for(j1;j<i;j) cout<<"*"; cout<<endl; } } ———————————————————————————…

Linux基礎入門學習筆記之二

第三節 用戶及文件權限管理 Linux用戶管理 Linux是可以實現多用戶登錄的操作系統 查看用戶who命令用于查看用戶 shiyanlou是當前登錄用戶的用戶名 pts/0中pts表示偽終端&#xff0c;后面的數字表示偽終端的序號。 后面是當前偽終端啟動時間 創建用戶創建用戶需要root權限&#…

java選填_java基礎填空選擇題

Core Java試題選擇填空題&#xff1a;全部為多選題&#xff0c;只有全部正確才能得分。1. 編譯java程序的命令是__B_;運行java程序的命令是____A____;產生java文擋的命令是_____D___;查詢java類型是否是serializable類型的命令是___C_____;產生java安全策略文件的命令是____E__…

這幾天有django和python做了一個多用戶博客系統(可選擇模板) 沒完成,先分享下...

這個TBlog已經全新改版了&#xff0c;更名為UUBlog 新版地址&#xff1a; 用Python和Django實現多用戶博客系統——UUBlog 斷斷續續2周時間吧&#xff0c;用django做了一個多用戶博客系統&#xff0c;現在還沒有做完&#xff0c;做分享下,以后等完善了再慢慢說 做的時候房展了博…

Hibernate的generator屬性

本文講述Hibernate的generator屬性的意義。Generator屬性有7種class&#xff0c;本文簡略描述了這7種class的意義和用法。[xhtml] view plaincopy <class name"onlyfun.caterpillar.User" table"USER"> <id name"id" type"stri…

java 對象池 博客_Java對象池技術的原理及其實現的小結

一起學習Java對象的生命周期大致包括三個階段&#xff1a;對象的創建&#xff0c;對象的使用&#xff0c;對象的清除。因此&#xff0c;對象的生命周期長度可用如下的表達式表示&#xff1a;T T1 T2 T3。其中T1表示對象的創建時間&#xff0c;T2表示對象的使用時間&#xff0c…

matlab中gatbx工具箱的添加

1. 從http://crystalgate.shef.ac.uk/code/下載工具箱壓縮包gatbx.zip 2. 解壓gatbx.zip&#xff0c;將其子文件夾genetic放在matlab安裝目錄toolbox文件夾下 3. 在matlab主窗口選擇File -> Set Path&#xff0c; 單擊"Add Folder"按鈕&#xff0c;找到工具箱所在…

C#與數據庫訪問技術總結(十七)

使用DataSet對象訪問數據庫 當對DataSet對象進行操作時&#xff0c;DataSet對象會產生副本&#xff0c;所以對DataSet里的數據進行編輯操作不會直接對數據庫產生影響&#xff0c;而是將DataRow的狀態設置為added、deleted或changed&#xff0c;最終的更新數據源動作將通過DataA…

MySQL數據高級查詢之連接查詢、聯合查詢、子查詢

2019獨角獸企業重金招聘Python工程師標準>>> 一、連接查詢 連接查詢: 將多張表(>2)進行記錄的連接(按照某個指定的條件進行數據拼接)。 連接查詢的意義: 在用戶查看數據的時候,需要顯示的數據來自多張表. 連接查詢: join, 使用方式: 左表 join 右表&#xff1b;左…

Oracle11g解鎖報錯SP2-0306-選項無效

普通用戶登錄isqlplus: (一)在瀏覽器中輸入URL &#xff08;http://localhost:5560/isqlplus&#xff09;。顯示登錄界面 這里只能用普通用戶進行登錄&#xff0c;因為要用sys登錄&#xff0c;必須用sys的DBA身份登錄。所以用普通用戶SCOTT&#xff0c;但是還未解鎖 問題:SP2-0…

java web登錄action_JavaWeb中登陸功能

首先我們要JavaWeb登陸的基本流程&#xff1a;JSP頁面發送請求——>Servlet——>Servlet通過調用方法從數據庫中得到數據并將結果返回頁面我們先建立三個jsp頁面&#xff0c;包括login.jsp(登陸頁面)、index.jsp(顯示登陸成功后的信息)、error.jsp(登錄失敗的頁面)&#…

Android Download Manager用法大全

http://www.trinea.cn/android/android-downloadmanager/ http://www.trinea.cn/android/android-downloadmanager-pro/轉載于:https://www.cnblogs.com/soaringEveryday/articles/4135204.html

Chrome瀏覽器無法觀看視頻,一直提示“adobe flash player 已過期” ?

很多新用戶在安裝了Chrome瀏覽器或者更新過的的時候&#xff0c;經常提示“ adobe flash player 已過期”的問題&#xff0c;反復提示&#xff0c;導致無法觀看視頻。于是從網上也找了很多辦法都沒有解決。這里給大家提供一個最完美的解決方案。經親自測試&#xff0c;完美解決…

關于JVM的垃圾回收GC的一些記錄

目錄 一、JVM內存區域劃分 二、從一個基本問題開始引入垃圾回收 三、GC作用的區域 三、如何確定一個對象是否可以被當成垃圾進行回收 &#xff08;1&#xff09;引用計數法 &#xff08;2&#xff09;可達性分析算法 &#xff08;3&#xff09;引用的類型 &#xff08;3…

同步與互斥

有數據交互的進程之間的關系主要有兩種,同步與互斥.所謂互斥,是指在不同進程之間的若干程序片斷,當某個進程運行其中一個程序片段時,其它進程就不能運行它們之中的任一程序片段,只能等到該進程運行完這個程序片段后才可以運行.所謂同步,是指在不同進程之間的若干程序片斷,它們的…

java 分號 轉義_java – 正則表達式和轉義和未轉義的分隔符

你可以使用正則表達式(?:\\.|[^;\\])*匹配未轉義分號之間的所有文本&#xff1a;List matchList new ArrayList();try {Pattern regex Pattern.compile("(?:\\\\.|[^;\\\\])*");Matcher regexMatcher regex.matcher(subjectString);while (regexMatcher.find())…

OpenCV cv::Mat類

using namespace cv; 1、Mat的聲明&#xff1a; Mat mMat(rows, cols, type); Mat mMat(Size(width,height), type); type指矩陣中元素的類型&#xff0c;可以使CV_8U&#xff08;無符號單字節像素&#xff09;&#xff0c;CV_8S&#xff08;有符號單字節像素&#xff09;&…

ubuntu-E:Encountered a section with no Package: header的解決辦法

ubuntu 11.04 出現了如下錯誤&#xff1a; E:Encountered a section with no Package: header 終端中輸入以下兩條命令&#xff1a; sudo rm /var/lib/apt/lists/* -vfsudo apt-get update 執行完了命令之后&#xff0c;軟件更新器應該會自動要求更新的&#xff0c;更新便是。 …