python迭代器及一點點yield

2021-09-29 11:15:23 字數 4503 閱讀 8345

python 裡的可迭代物件都有以下方法

def

__iter__

(self,

*args,

**kwargs)

:# real signature unknown

""" implement iter(self). """

pass

實現了iter(self) 函式

接下來檢視iter() 函式

def

iter

(source, sentinel=

none):

# known special case of iter

""" iter(iterable) -> iterator

iter(callable, sentinel) -> iterator

get an iterator from an object. in the first form, the argument must

supply its own iterator, or be a sequence.

in the second form, the callable is called until it returns the sentinel.

"""pass

iter() 函式可以有乙個或兩個引數

有乙個引數時,iter(iterable) -> iterator ,get an iterator from an object(獲取物件的迭代器),in the first form, the argument must

supply its own iterator, or be a sequence.(在第一種形式中,即只有乙個引數的時候,該物件自身需要提供迭代器,也就是有自己的iter函式,或者該物件是乙個佇列)

python 的基本資料型別中,有iter函式的有字串(str),列表(list),元組(tuple),集合(set),字典(dict)

接下來去看看官方文件對iter()函式的解釋

python各種版本的文件

3.6.4版本的iter()函式直通車

iter(object[, sentinel])方法在給定第二個引數的時候,則object必須是可呼叫的物件,iter()方法建立了乙個迭代器,每次呼叫這個迭代器的__next()__方法的時候,都會呼叫object引數,如果next()方法返回值等於sentinel,將會引發stopiteration,不等於則返回方法返回值.

這裡需要注意,python裡有個函式callable(object) 可以判斷乙個物件是否是可呼叫的,如果物件顯示可呼叫,則返回true,否則返回false,返回true的話,呼叫有可能失敗,如果返回false的話,永遠不可能被呼叫.類是可以被呼叫的,呼叫乙個類返回乙個新例項物件,如果例項物件所屬的類有個__call()__方法的話,該例項物件也是可以被呼叫的.

callable() 這個函式在python 3.0被刪除,後來在3.2版本裡又回歸了.

#例子一

classa:

def__init__

(self)

: self.list1 =[1

,2,3

,4,5

,6,7

]print

('init()被呼叫'

)def

__call__

(self)

:print

('call()被呼叫'

)return

next

(self)

def__iter__

(self)

:print

('iter()被呼叫'

) self.i =

0return self.list1

def__next__

(self)

:if self.i <

len(self.list1)

:print

('next()方法呼叫'

) next_value = self.list1[self.i]

self.i +=

1return next_value

else

:raise stopiteration

if __name__ ==

'__main__'

:print

(callable

(a()))

# init()被呼叫 true

a = a(

)print

(callable

(a))

# init()被呼叫 true

i =iter

(a,5

)print

(type

(i))

# for x in i:

print

(x)'''

call()被呼叫

next()方法呼叫

1call()被呼叫

next()方法呼叫

2call()被呼叫

next()方法呼叫

3call()被呼叫

next()方法呼叫

4call()被呼叫

next()方法呼叫

'''

#例子二

i =0

defgetnum()

:global i

i +=

1return i

print

(callable

(getnum)

)a =

iter

(getnum,5)

for x in a:

print

(x)'''

true12

34'''

yieldyield表示式在定義生成器函式或非同步生成器函式時使用,因此只能在函式定義的主體中使用,在函式體中使用yield會使該函式稱為生成器函式.

呼叫生成器函式時,將返回乙個名為生成器的迭代器,該生成器控制著生成器函式的執行,當呼叫生成器的方法的時候,開始執行生成器函式.執行到第乙個yield表示式的時候,該生成器函式被掛起,然後將expression_list格式的值返回給生成器的呼叫方,

expression_list ::= expression ( 「,」 expression )* [","]

這裡掛起的意思是,保留所有的區域性狀態,包括區域性變數的當前繫結值,指令指標,內部堆疊和任何異常處理的狀態.當呼叫生成器的方法時,恢復執行狀態,類似於生成器函式被重新呼叫一樣,只不過是從上次掛起的地方開始.之後的yield表示式的值取決於恢復執行狀態時被呼叫的生成器的方法.

如下例子debug分析具體過程:

# -*- coding:utf-8 -*-

defgetnum

(n):

a =1while

true

:if a > n:

return

yield a

print

(a, a *

2, a *3)

a +=

1if __name__ ==

'__main__'

: num = getnum(3)

print

(type

(num)

)while

true

:try

:next

(num)

except

: exit(

)

在num=getnum(3) 和 next(num) 處打斷點,debug執行程式

getnum()返回乙個num,型別為generator

當程式執行到next()的時候,getnum()開始執行,執行到yield的時候不往下繼續,此時a=1,next()執行完

然後開始第二次執行next(),跳到getnum()函式,繼續執行yield之後的**,print(a, a * 2, a * 3),[結果是 1,2,3]然後a變成2,繼續迴圈,判斷if**,第二次執行到yield,然後不往下繼續,next()執行完

然後繼續執行next()所在的迴圈,第三次執行next(),然後跳轉到getnum()函式,執行print(a, a * 2, a * 3),[結果是2 4 6],a自增1變成3,繼續執行getnum()函式的迴圈,if判斷,yield a,不往下繼續執行,跳到next()執行完

執行next()所在迴圈,第四次執行next(),跳轉到getnum(),繼續執行,print(a, a * 2, a * 3),[結果是 3 6 9],a自增1變成4,if判斷通過getnum()函式return,跳到next(),程式捕獲異常,退出

後續的協程,yield from 在之後多執行緒的地方研究.

一點點感想

寫在這喧囂與寂寞的世界 今天我與chen在風初停的早上跑去借書,借了安妮的 清醒記 兩本三毛的書和一本yilan的旅行與味蕾的書。從圖書館出來,風似乎有些冷,想到又要到那陰冷的梅花館坐在又涼又硬的椅子上上一節乏味的數學課我們便都不約而同的想到了逃課。帶著心裡的負罪感我們躲進八食取暖。無意中我們嘗到了...

一點點感悟

這兩天一直在努力的調整狀態,考慮了很多,也想通了很多,因為看開了,所以狀態也好了很多。明白了,一件事情的兩面性,壞的一面會使自己痛苦不堪,好的一面會使自己心情愉快。看了一篇文章,感觸很大,裡面有很多啟發自己的語句。二十幾歲的人,除了愛情之外,還需要有一項能使自己生活的本領 要把自己的感觸 心情和生活...

一點點想法

最近公司要做個專案,用到進銷存系統,考查了好幾個,都不是很滿意 要麼功能上不行,要麼 上不行 突然在想,如果能用php做乙個,將是個不錯的選擇,因為進銷存大部分都是內部人使用,併發量要求並不是很高,主要是資料準確性和安全性,我想這兩方面重不在語言,另外乙個麻煩的地方是報表這塊,可以用其它語言來單獨處...