日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

【Python之路】特別篇

 highoo 2019-03-20
生成器(constructor)

  生成器函數(shù)在Python中與迭代器協(xié)議的概念聯(lián)系在一起。包含yield語句的函數(shù)會被特地編譯成生成器 !!!

  當(dāng)函數(shù)被調(diào)用時,他們返回一個生成器對象,這個對象支持迭代器接口。

  不像一般的函數(shù)會生成值后退出,生成器函數(shù)在生成值后會自動掛起并暫停他們的執(zhí)行和狀態(tài),他的本地變量將保存狀態(tài)信息,這些信息在函數(shù)恢復(fù)時將再度有效

創(chuàng)建生成器方式有兩種:

方法一:

1
s = ( x for x in range(5) )

方法二:

1
2
3
def foo():
    print('OK')
    yield 1

例子:

1
2
3
4
5
6
def g(n):
    for i in range(n):
        yield i **2
for i in g(5):
    print(i)

要了解他的運行原理,我們來用next方法看看:

1
2
3
4
5
6
7
8
9
10
11
t = g(5)
print(t.__next__())      # 0
print(t.__next__())      # 1
print(t.__next__())      # 4
print(t.__next__())      # 9
print(t.__next__())      # 16
print(t.__next__())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

在運行完5次next之后,生成器拋出了一個StopIteration異常,迭代終止。

send(msg) 與 next()

了解了next()如何讓包含yield的函數(shù)執(zhí)行后,我們再來看另外一個非常重要的函數(shù)send(msg)。

其實next()和send()在一定意義上作用是相似的,區(qū)別是send()可以傳遞yield表達(dá)式的值進(jìn)去,而next()不能傳遞特定的值,只能傳遞None進(jìn)去。因此,我們可以看做

c.next() 和 c.send(None) 作用是一樣的。

1
2
3
4
5
6
7
8
9
10
11
def g(n):
    for i in range(n):
        ret = yield i **2
        print(ret)
t = g(5)
print(t.__next__())
print(t.send('Hello'))
# 0 Hello 1

需要注意的是,第一次調(diào)用時,請使用next()語句或是send(None),不能使用send發(fā)送一個非None的值,否則會出錯的,因為沒有yield語句來接收這個值。

send(msg) 和 next()是有返回值的,它們的返回值很特殊,返回的是yield表達(dá)式的參數(shù) !

執(zhí)行順序是:遇到y(tǒng)ield 先返回值,等下次再進(jìn)入時再用 msg 進(jìn)行賦值?。。?/p>

再來看一個yield的例子,用生成器生成一個Fibonacci數(shù)列:

1
2
3
4
5
6
7
8
9
10
def fab(max):
    a, b = 0, 1
    while a < max:
        yield a
        a, b = b, a + b
for i in fab(20):
    print(i)
# 0 1 1 2 3 5 8 13

另一個 yield 的例子來源于文件讀取。

1
2
3
4
5
6
7
8
9
def read_file(fpath):
   BLOCK_SIZE = 1024
   with open(fpath, 'rb') as f:
       while True:
           block = f.read(BLOCK_SIZE)
           if block:
               yield block
           else:
               return

  

迭代器(iterator)

  for循環(huán)可以用于Python中的任何類型,包括列表、元祖等等,實際上,for循環(huán)可用于任何“可迭代對象”!

  迭代器是一個實現(xiàn)了迭代器協(xié)議的對象,Python中的迭代器協(xié)議就是有next方法的對象會前進(jìn)到下一結(jié)果,而在一系列結(jié)果的末尾是,則會引發(fā)StopIteration。

  任何這類的對象在Python中都可以用for循環(huán)或其他遍歷工具迭代,迭代工具內(nèi)部會在每次迭代時調(diào)用next方法,并且捕捉StopIteration異常來確定何時離開。

  使用迭代器一個顯而易見的好處就是:每次只從對象中讀取一條數(shù)據(jù),不會造成內(nèi)存的過大開銷。

注意

  判斷迭代器的條件是:

  1. 有__iter__ 方法

  2. 有__next__ 方法

  所有的生成器都是迭代器!

迭代器例子:

比如要逐行讀取一個文件的內(nèi)容,利用readlines()方法,我們可以這么寫:

1
2
for line in open("test.txt").readlines():
    print (line)

這樣雖然可以工作,但不是最好的方法。因為他實際上是把文件一次加載到內(nèi)存中,然后逐行打印。當(dāng)文件很大時,這個方法的內(nèi)存開銷就很大了。

利用file的迭代器,我們可以這樣寫:

1
2
for line in open("test.txt"):
    print (line)

這是最簡單也是運行速度最快的寫法,他并沒顯式的讀取文件,而是利用迭代器每次讀取下一行。

for 循環(huán)實質(zhì)

  1. 調(diào)用 __iter__ 方法將可迭代對象轉(zhuǎn)換成迭代器

  2. 對迭代器對象不斷調(diào)用 __next__ 方法

  3. 處理StopIteration 異常

View Code

 

可迭代對象(iterable)

  判斷條件:內(nèi)部具有 __iter__ 方法

1
2
3
4
5
6
from collections import Iterable,Iterator
print(isinstance(range(1),Iterable))
print(isinstance(range(1),Iterator))
print(isinstance(list(),Iterable))
print(isinstance(list(),Iterator))

  

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多