① python遞歸生成器問題
如果調用 flatten3([[1,2],3])的話
for sublist in nested:
for element in fatten(sublist):
yield element
sublist分別為[1,2]和3
遞歸調用 fattern([1,2])返回一個包含1,2的子生成器,for element in fatten返回1,2用yield語句將1,2放入父生成器中,有了yield父生成器中才會有子生成器中的值
遞歸調用 flatten(3) TypeError執行yield 3,返回一個包含3的子生成器,yield element,3才會包含在父生成中
② 關於python的遞歸生成器
加了點注釋,自己看吧,下次不要用圖片了,直接拷貝代碼吧
#-*-coding:cp936-*-
defflatten(nested):
try:
#這里首先檢查nested是否可迭代,不可迭代則拋出TypeError
forsublistinnested:
#可迭代,那麼遞歸,檢查sublist是否還可以迭代
forelementinflatten(sublist):
#這里的element必定不可迭代,已經完全展開,因此使用yield輸出,返回上層
#如果sublist是不可迭代的,那麼flatten(sublist)返回的生成器就只有一個數據,就是sublist
#yieldelement也相當於yieldsublist
#否則的話,flatten(sublist)返回的是展開的數據
yieldelement
exceptTypeError:
#nested不可迭代,直接返回上層即可
yieldnested
③ Python生成器,遞歸時代碼執行順序
生成器就是用來生成有規律的值的
含有yield語句的函數就是生成器,counter(5)表示用參數start_at=5為初值調用生成
器,將函數對象賦值給count,count指向生成
器對象
每次調用生成器的next方法,就執行代碼到yield語句處返回yield後的值,因此第一次調用
執行到yield返回
,下次調用
next時從上次執行處接著執行到yield語句處,所以生成器中可以用while
True語句不用擔心死循環
yield這個表達式的值就是None,所以val一直是None
④ python遞歸生成器
defflattern(nested):
try:
iftype(nested)==type(""):
raiseTypeError()
forsublistinnested:
forelementinflattern(sublist):
yieldelement
exceptTypeError:
yieldnested
nested=[[1,2],[3,4],[5],6]
foriinflattern(nested):
printi
生成器的作用就是產生一個可迭代對象,可以在for這樣的語句中使用,yield element語句的作用就是將element添加到這個可迭代對象
def flattern(nested):
try:
for sublist in nested:
for element in flattern(sublist): #迭代flattern(子列表)所產生的生成器
yield element #對flattern的遞歸調用只是生成了新的生成器,得將這些生成器中的值添加到當前生成器
except TypeError:
yield nested #如果變數nested不可迭代,for語句會出現TypeError錯誤,這時將nested添加到當前生成器中
在try開頭加上了
if type(nested)==type(""):
raise TypeError()
因為字元是一直可以迭代的,如果不處理,如果參數中有字元串會無限遞歸下去
這個函數的作用就是將子列表完全擴展開產生一個生成器
⑤ python里yield的問題
'''
python中生成器是迭代器的一種,使用yield返回函數值。
每次調用yield會暫停,可以使用next()函數恢復生成器。
'''
deftest():
print('first')
yield1
print('second')
yield2
print('end')
r=test()
x=next(r)
print(x)
x=next(r)
print(x)
x=next(r)
print(x)
⑥ python的關鍵字yield有什麼作用
yield是python中定義為生成器函數,其本質是封裝了 __iter__和__next__方法 的迭代器;
與return返回的區別:return只能返回一次值,函數就終止了,而yield能多次返回值,每次返回都會將函數暫停,下一次next會從上一次暫停的位置繼續執行;
以下用示例說明:
deftest(a,b):
print("fromtest(),a+b=%d"%(a+b))
return("我是return返回的")
deftest_yield(a,b): #函數體中有yield關鍵字,函數就可以稱為生成器函數
print("fromtest_yield,a+b=%d"%(a+b))
yield("我是第一次碰到yield關鍵字返回的") #程序運行時碰到yield,退出函數體並記錄位置,下次調用跳過之前運行的代碼
print("fromtest_yield,a*2=%d"%(a*2))
yield("我是第二次調用碰到yield關鍵字返回的")
print(test(11,33))
g=test_yield(11,33)
print(next(g)) #通過next()調用生成器函數
print(next(g)) #第二次調用生成器函數
'''
執行結果:
fromtest(),a+b=44
我是return返回的
fromtest_yield,a+b=44
我是第一次碰到yield關鍵字返回的
fromtest_yield,a*2=22
我是第二次調用碰到yield關鍵字返回的
'''
⑦ python中return和yield怎麼用的兩個有什麼區別
常看到別人使用或討論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等等的問題
關於yield,樓下kanchi240說的完全正確。我就不補充了。
想說的是。你這個用yield的函數的邏輯可能存在問題。入口參數nested是一個數組,函數里for sublist in nested被執行的時候,如果nested被改變就不合理,會產生一個異常,也許你設計的初衷就是如此。
defflatten(nested):
try:
forsublistinnested:
forelementinflatten(sublist):
yieldelement
exceptTypeError:
yieldnested
if__name__=="__main__":
forxinflatten(nested=[1,[2,[3]]]):
printx,type(x)
輸出結果是
1<type 'int'>
2<type 'int'>
3<type 'int'>
你這個好象又是遞歸函數。分解一下步驟是這樣子。
flatten(nested=[1,[2,[3]]])
sublist=1
for element in flatten(sublist):此處在子調用異常,輸出1, 但是它被遞歸函數的循環再次yield。
下面依次類推。
我把程序修改了一下,可能看起來更清晰。
defflatten(nested,level=0):
try:
forsublistinnested:
print"sublist:",sublist,type(sublist)
forelementinflatten(sublist,level+1):
printlevel,"yield",element
yieldelement
exceptTypeError:
printlevel,'yieldtypeerror',nested,type(nested)
yieldnested
if__name__=="__main__":
forxinflatten(nested=[1,[2,[3]]]):
printx,type(x)
輸出結果是
sublist: 1 <type 'int'>
1 yield type error 1 <type 'int'>
0 yield 1
1 <type 'int'>
sublist: [2, [3]] <type 'list'>
sublist: 2 <type 'int'>
2 yield type error 2 <type 'int'>
1 yield 2
0 yield 2
2 <type 'int'>
sublist: [3] <type 'list'>
sublist: 3 <type 'int'>
3 yield type error 3 <type 'int'>
2 yield 3
1 yield 3
0 yield 3
3 <type 'int'>