pythonyield與return
① python中yield和return究竟有什麼區別,怎麼用
常看到別人使用或討論yield語法,能搜到的中文解釋卻不多,今天決心搞定yield,把暫時的理解貼到這里.
搞定yield之前: 疊代器(iterator)
發現yield: 生成器(constructor)
使用yield: 遞歸調用
1. iterator
疊代器最簡單例子應該是數組下標了,且看下面的c++代碼:
int array[10];
for ( int i = 0; i < 10; i++ )
printf("%d ", array[i]);
疊代器工作在一個容器里(array[10]),它按一定順序(i++)從容器里取出值(array[i])並進行操作(printf("%d ", array[i])。
上面的代碼翻譯成python:
array = [i for i in range(10)]
for i in array:
print i,
for i in array幹了什麼(別亂想)?首先,array作為一個list是個容器,其次list這個內建類型有默認的next行為,python發現這些之後采 取的秘密的沒被各位看到的動作是:拿出array這丫容器的疊代器,從裡面next一下把值給i供for循環主體處置,for把這個值print了。
現在的問題是數據可以做容器疊代,代碼可以嗎?
怎麼不行,碗碟可以用來放菜,wk們不就聯想出用nt盛嗎,當然我們的yield不會那麼yellow + bt
2. constructor
怎麼把函數變成constructor? 在函數體里有yield就行了!
def gen():
print 'enter'
yield 1
print 'next'
yield 2
print 'next again'
for i in gen():
print i
各位!python看到gen函數里出現yield,知道可以用next了,問題是怎麼對代碼這個容器玩next?
從容器里拿到iterator的時候它還什麼也不是,處在容器入口處,對於數組來說就是下標為-1的地方,對於函數來說就是函數入口嘛事沒干,但是萬事俱備就欠next。
開始for i in g,next讓itreator爬行到yield語句存在的地方並返回值,
再次next就再爬到下一個yield語句存在的地方並返回值,依次這樣直到函數返回(容器盡頭)。
您一定看出來上面代碼的輸出是:
enter
1
next
2
next again
如果沒看出來請不要往下看了免得反被yield搞定。
3. 使用yield
yield的代碼疊代能力不但能打斷函數執行還能記下斷點處的數據,下次next書接上回,這正是遞歸函數需要的。
例如中序遍歷二叉樹:
(應該是David Mertz寫的)
def inorder(t):
if t:
for x in inorder(t.left):
yield x
yield t.label
for x in inorder(t.right):
yield x
for n in inorder(tree)
print n
當然yield這種代碼next的能力還可以用在其它方面,發現拍案的在貼咯。
② 如何理解Python中的yield用法
Python中的yield用於創建一個可迭代的生成器,它允許函數逐個生成值,而不是一次性返回所有結果。以下是關於yield用法的詳細解釋:
與return的區別:
- return會一次性返回函數的所有結果,並導致程序終止,局部變數也會被銷毀。
- yield則創建一個生成器,通過for循環或next方法逐個生成值,函數在遇到yield時會暫停,並保持局部變數的狀態,直到生成器被遍歷完。
生成器的概念:
- 生成器是由yield定義的函數,調用它會返回一個生成器對象。
- 當調用生成器對象時,函數會在遇到yield時暫停,保存當前狀態。
- 在下一次調用next方法時,函數會從上次暫停的點繼續執行,直到遇到下一個yield或函數結束。
生成器的用途:
- 生成器在處理大量數據時特別有用,因為它們可以按需生成數據,避免了一次性載入所有數據導致的內存消耗問題。
- 生成器還可以用於遵循特定邏輯生成數據,如生成斐波那契數列等。
示例:
- 一個簡單的生成器函數,使用yield逐個生成數字1, 2, 3。
- 每次調用next方法時,函數會按順序生成下一個數字,並暫停在當前的yield語句處。
總結:yield是Python中一個強大的特性,它允許函數創建生成器,以逐個生成值的方式處理數據,而不是一次性返回所有結果。這使得生成器在處理大量數據或遵循特定邏輯生成數據時非常高效和內存友好。