中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

南京網(wǎng)站搭建公司網(wǎng)絡(luò)推廣公司專業(yè)網(wǎng)絡(luò)

南京網(wǎng)站搭建公司,網(wǎng)絡(luò)推廣公司專業(yè)網(wǎng)絡(luò),魯班設(shè)計(jì)工作平臺,大連做網(wǎng)站孫曉龍大家好,小編來為大家解答以下問題,python生成器有幾種寫法,python生成器函數(shù)例子,今天讓我們一起來看看吧! 本文部分參考:Python迭代器,生成器–精華中的精華 https://www.cnblogs.com/deeper/p…

大家好,小編來為大家解答以下問題,python生成器有幾種寫法,python生成器函數(shù)例子,今天讓我們一起來看看吧!

本文部分參考:Python迭代器,生成器–精華中的精華 https://www.cnblogs.com/deeper/p/7565571.html

一 迭代器和可迭代對象

迭代器是訪問集合元素的一種方式?;疖囶^采集器AI偽原創(chuàng)。迭代器只能往前不會(huì)后退。迭代器的一大優(yōu)點(diǎn)是不要求事先準(zhǔn)備好整個(gè)迭代過程中所有的元素,僅僅在迭代到某個(gè)元素時(shí)才計(jì)算該元素,而在這之前或之后,元素可以不存在或者被銷毀。這個(gè)特點(diǎn)使得它特別適合用于遍歷一些巨大的或是無限的集合,比如幾個(gè)G的文件。

特點(diǎn):

a)訪問者不需要關(guān)心迭代器內(nèi)部的結(jié)構(gòu),僅需通過next()方法或不斷去取下一個(gè)內(nèi)容

b)不能隨機(jī)訪問集合中的某個(gè)值 ,只能從頭到尾依次訪問

c)訪問到一半時(shí)不能往回退

d)便于循環(huán)比較大的數(shù)據(jù)集合,節(jié)省內(nèi)存

e)也不能復(fù)制一個(gè)迭代器。如果要再次(或者同時(shí))迭代同一個(gè)對象,只能去創(chuàng)建另一個(gè)迭代器對象。

enumerate()的返回值就是一個(gè)迭代器,我們以enumerate為例:

a = enumerate(['a','b'])for i in range(2):    #迭代兩次enumerate對象for x, y in a:print(x,y)print(''.center(50,'-'))

結(jié)果:

0 a
1 b
-----------------------分割線------------------------
-----------------------分割線------------------------

可以看到再次迭代enumerate對象時(shí),沒有返回值。

我們可以用linux的文件處理命令vim和cat來理解一下:

a) 讀取很大的文件時(shí),vim需要很久,cat是毫秒級;因?yàn)関im是一次性把文件全部加載到內(nèi)存中讀取;而cat是加載一行顯示一行

b) vim讀寫文件時(shí)可以前進(jìn),后退,可以跳轉(zhuǎn)到任意一行;而cat只能向下翻頁,不能倒退,不能直接跳轉(zhuǎn)到文件的某一頁(因?yàn)樽x取的時(shí)候這個(gè)“某一頁“可能還沒有加載到內(nèi)存中)。

正式進(jìn)入python迭代器之前,我們先要區(qū)分兩個(gè)容易混淆的概念:可迭代對象(Iterable)和迭代器(Iterator)

1.1可迭代對象

定義:迭代器是一個(gè)對象,不是一個(gè)函數(shù)。只要它定義了可以返回一個(gè)迭代器的__iter__方法,或者定義了可以支持下標(biāo)索引的__getitem__方法,那么它就是一個(gè)可迭代對象。

注意: 集合數(shù)據(jù)類型,如list、tuple、dict、set、str都是可迭代對象Iterable,卻不是迭代器Iterator。

如何判斷一個(gè)對象是可迭代對象呢?可以通過collections模塊的Iterable類型判斷:

from collections import Iterable
print(isinstance([], Iterable))
print(isinstance({}, Iterable))
print(isinstance('abc', Iterable))
print(isinstance({'name':'join','age':23},Iterable))
print(isinstance(set([2,3]),Iterable))

結(jié)果為:

True
True
True
True
True

再看:

from collections import Iterator
print(isinstance([], Iterator))
print(isinstance({}, Iterator))
print(isinstance('abc', Iterator))
print(isinstance({'name':'join','age':23},Iterator))
print(isinstance(set([2,3]),Iterator))

結(jié)果為:

False
False
False
False
False

1.2迭代器

定義:任何實(shí)現(xiàn)了__iter__()和__next__()(python2中實(shí)現(xiàn)next())方法的對象都是迭代器,__iter__返回迭代器自身,__next__返回容器中的下一個(gè)值。

這里我們來看一下迭代器和可迭代對象的使用方法。

問題:不適用for,while以及下表索引,怎么遍歷一個(gè)list?

l1=[2,3,5]
iter_l1 = l1.__iter__() 
# 或者iter(iter_l1)
# iter(iter_l1)是python的內(nèi)置函數(shù),
# l1.__iter__()調(diào)用的是l1對象的__iter__()方法。
# 下面的next()函數(shù)和__iter__()函數(shù)類似。
print(next(iter_l1)) # 或print(iter_l1.__next__()
print(next(iter_l1))
print(next(iter_l1))
print(next(iter_l1))

結(jié)果為:

2
3
5
---------------------------------------------------------------------------
StopIteration                             Traceback (most recent call last)
<ipython-input-126-eb58865cb644> in <module>4 print(next(iter_l1))5 print(next(iter_l1))
----> 6 print(next(iter_l1))

結(jié)論:思路就是,先得到當(dāng)前對象(當(dāng)前對象是可迭代對象)的迭代器,然后每次執(zhí)行next(iter_l1)就可以得到當(dāng)前對象的一個(gè)值。

修改一下:

l1=[2,3,5]
iter_l1 = l1.__iter__() 
for i in iter_l1:print(i,end=',')

結(jié)果為:

2,3,5,

再次執(zhí)行for語句如下:

for i in iter_l1:print(i,end=',')

此次返回結(jié)果為空,可以看到迭代器只能遍歷一次對象,不能重復(fù)遍歷。由于for語句可以自動(dòng)處理StopIteration異常,所以這里沒有報(bào)出StopIteration,而是沒有任何結(jié)果。

看一個(gè)例子。我們想得到Fibonacci數(shù)列,思路是定義一個(gè)可迭代對象類Fib;然后在定義一個(gè)迭代器類FibIterator,使用方式是:
① 實(shí)例化一個(gè)可迭代對象: fib = Fib()
② 得到fib的一個(gè)迭代器: fib_iter = iter(fib)
③ 然后每次調(diào)用next(fib_iter)可得到fibonacci數(shù)列中的一個(gè)數(shù)。

class FibIterator():'''定義迭代器類'''def __init__(self,num,a,b,current):self.num = numself.a = aself.b = bself.current = currentdef __iter__(self):return selfdef __next__(self):if(self.num-1>=0):self.num = self.num-1self.current = self.aself.a = self.bself.b = self.b+self.current   #以上兩步賦值操作可省略中間變量直接寫為self.a,self.b = self.b,self.a+self,b return self.currentelse: raise StopIterationclass Fib:'''定義可迭代對象所屬類'''def __init__(self,num): #num表示該數(shù)列的長度self.a = 1self.b = 2self.current=self.aself.num = numdef __iter__(self):return FibIterator(self.num,self.a,self.b,self.current)fib = Fib(20)
fib_iter = iter(fib)
for i in range(20):print(next(fib_iter),end=',')

結(jié)果為:

1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,

這里定義的Fibonacci類的__init__函數(shù)有一個(gè)參數(shù)num,表示一共得到幾個(gè)fibonacci數(shù)。

由于可迭代對象是實(shí)現(xiàn)了__iter__()方法的,迭代器對象是實(shí)現(xiàn)了__iter__()和__next__()方法的,能否只定義一個(gè)迭代器類呢?

試一下。

class Fib:def __init__(self,num):self.num = numself.a = 1self.b = 2self.current = self.adef __iter__(self):return selfdef __next__(self):if(self.num-1>=0):self.num = self.num-1self.current = self.aself.a = self.bself.b = self.b+self.current   #以上兩步賦值操作可省略中間變量直接寫為self.a,self.b = self.b,self.a+self,b return self.currentelse: raise StopIterationfib = Fib(10)
for i in fib:print(i,end=',')

結(jié)果為:

1,2,3,5,8,13,21,34,55,89,

當(dāng)我們再次執(zhí)行for語句時(shí),

for i in fib:print(i,end=',')

同上面的分析一樣,結(jié)果為空。如果想再次得到fibonacci數(shù)列的前10個(gè)數(shù),就必須重新實(shí)例化Fib對象。

結(jié)論:為什么不只保留Iterator的接口而還需要設(shè)計(jì)Iterable呢?

因?yàn)榈鞯淮我院缶涂樟?#xff0c;那么如果list,dict也是一個(gè)迭代器,迭代一次就不能再繼續(xù)被迭代了,這顯然是反人類的;所以通過__iter__每次返回一個(gè)獨(dú)立的迭代器,就可以保證不同的迭代過程不會(huì)互相影響。

另外,迭代器是惰性的,只有在需要返回下一個(gè)數(shù)據(jù)時(shí)它才會(huì)計(jì)算。所以,Iterator甚至可以表示一個(gè)無限大的數(shù)據(jù)流,例如全體自然數(shù)。而使用list是永遠(yuǎn)不可能存儲全體自然數(shù)的。

下面的例子得到全體自然數(shù)(下面我們用生成器可以得到更簡單的寫法)。

class Natural:def __init__(self):passdef __iter__(self):return NaturalIterator()
class NaturalIterator:def __init__(self):self.beg=0self.current=self.begdef __iter__(self):return selfdef __next__(self):self.current += 1return self.current   # 顯示前20個(gè)自然數(shù)
n1=Natural()
n1_iter = iter(n1)
for i in range(20):print(next(n1_iter),end=',')

結(jié)果為:

1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,

作業(yè):使用迭代器和可迭代對象實(shí)現(xiàn)得到全體fibonacci數(shù)。

二 生成器

2.1 生成器的定義和使用

定義:生成器其實(shí)是一種特殊的迭代器,它不需要再像上面的類一樣寫__iter__()和__next__()方法了,只需要一個(gè)yiled關(guān)鍵字。

生成器一定是迭代器(反之不成立)。

Python有兩種不同的方式提供生成器:

  1. 生成器函數(shù):常規(guī)函數(shù)定義,但是,使用yield語句而不是return語句返回結(jié)果。 yield語句一次返回一個(gè)結(jié)果,在每個(gè)結(jié)果中間,掛起函數(shù)的狀態(tài),以便下次重它離開的地方繼續(xù)執(zhí)行
  2. 生成器表達(dá)式:類似于列表推導(dǎo),但是,生成器返回按需產(chǎn)生結(jié)果的一個(gè)對象, 而不是一次構(gòu)建一個(gè)結(jié)果列表

我們先用一個(gè)例子說明一下:

def generate_even():i=0while True:if i%2==0:yield ii += 1g=generate_even()
dir(g) # 可以看到里面有__iter__()方法和__next__()方法,所以生成器也是迭代器。for i in range(10):print(g.__next__(),end=',')

結(jié)果為:

0,2,4,6,8,10,12,14,16,18,

現(xiàn)在解釋一下上面的代碼:

我們知道,一個(gè)函數(shù)只能返回一次,即return以后,這次函數(shù)調(diào)用就結(jié)束了;

但是生成器函數(shù)可以暫停執(zhí)行,并且通過yield返回一個(gè)中間值,當(dāng)生成器對象的__next__()方法再次被調(diào)用的時(shí)候,生成器函數(shù)可以從上一次暫停的地方繼續(xù)執(zhí)行,直到下一次遇到y(tǒng)ield語句(此時(shí)會(huì)返回yield后面的值,如果有的話)或者觸發(fā)一個(gè)StopIteration。

了解協(xié)同程序:
a) 生成器的另外一個(gè)方面是協(xié)同程序的概念。協(xié)同程序是可以運(yùn)行的獨(dú)立函數(shù)調(diào)用,可以暫停或者掛起,并從程序離開的地方繼續(xù)或者重新開始。

b) 可以在調(diào)用者和被調(diào)用的之間協(xié)同程序通信。

c) 在程序暫停時(shí)可以傳參:舉例來說,當(dāng)協(xié)同程序暫停時(shí),我們?nèi)钥梢詮钠渲蝎@得一個(gè)中間的返回值,當(dāng)調(diào)用回到程序中時(shí),能夠傳入額外或者改變了的參數(shù),但是仍然能夠從我們上次離開的地方繼續(xù),并且所有狀態(tài)完整。

生成器表達(dá)式類似于列表推導(dǎo)式,只是把[]換成(),這樣就創(chuàng)建了一個(gè)生成器。

gen = (x for x in range(10))

下面我們用生成器來實(shí)現(xiàn)前面的fibonacci數(shù)列和全體自然數(shù)。

# 生成前n個(gè)fibonacci數(shù)
def fib(n):a, b = 0, 1count=0while True:if(count>n):breakcount += 1yield ba, b = b, a+bf = fib(20)
for item in f:print(item,end=',')

結(jié)果為:

1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,
def Natural():n=0while True:yield nn += 1
g_n1=Natural()
for i in range(20):print(next(g_n1),end=',')

結(jié)果為:

0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,

2.2 send方法

生成器函數(shù)最大的特點(diǎn)是可以接受外部傳入的一個(gè)變量,并根據(jù)變量內(nèi)容計(jì)算結(jié)果后返回。這是生成器函數(shù)最難理解的地方,也是最重要的地方,協(xié)程的實(shí)現(xiàn)就全靠它了。

看一個(gè)小貓吃魚的例子:

def cat():print('我是一只hello kitty')while True:food = yieldif food == '魚肉':yield '好開心'else:yield '不開心,人家要吃魚肉啦'

中間有個(gè)賦值語句food = yield,可以通過send方法來傳參數(shù)給food,試一下:

情況1)

miao = cat()    #只是用于返回一個(gè)生成器對象,cat函數(shù)不會(huì)執(zhí)行
print(''.center(50,'-'))
print(miao.send('魚肉'))

結(jié)果:

Traceback (most recent call last):
--------------------------------------------------File "C:/Users//Desktop/Python/cnblogs/subModule.py", line 67, in <module>print(miao.send('魚肉'))
TypeError: can't send non-None value to a just-started generator

看到了兩個(gè)信息:

a)miao = cat() ,只是用于返回一個(gè)生成器對象,cat函數(shù)不會(huì)執(zhí)行

b)can’t send non-None value to a just-started generator;不能給一個(gè)剛創(chuàng)建的生成器對象直接send值

改一下,情況2)

miao = cat()
miao.__next__()
print(miao.send('魚肉'))

那么到底send()做了什么呢?send()的幫助文檔寫的很清楚,’’‘Resumes the generator and “sends” a value that becomes the result of the current yield-expression.’’’;可以看到send依次做了兩件事:

a)回到生成器掛起的位置,繼續(xù)執(zhí)行

b)并將send(arg)中的參數(shù)賦值給對應(yīng)的變量,如果沒有變量接收值,那么就只是回到生成器掛起的位置

但是,我認(rèn)為send還做了第三件事:

c)兼顧__next__()作用,掛起程序并返回值,所以我們在print(miao.send(‘魚肉’))時(shí),才會(huì)看到’好開心’;其實(shí)__next__()等價(jià)于send(None)

所以當(dāng)我們嘗試這樣做的時(shí)候:

def cat():print('我是一只hello kitty')while True:food = yieldif food == '魚肉':yield '好開心'else:yield '不開心,人家要吃魚肉啦'miao = cat()
print(miao.__next__())
print(miao.send('魚肉'))
print(miao.send('骨頭'))
print(miao.send('雞肉'))

就會(huì)得到這個(gè)結(jié)果:

我是一只hello kitty
None
好開心
None
不開心,人家要吃魚肉啦

我們按步驟分析一下:

a)執(zhí)行到print(miao.next()),執(zhí)行cat()函數(shù),print了”我是一只hello kitty”,然后在food = yield掛起,并返回了None,打印None

b)接著執(zhí)行print(miao.send(‘魚肉’)),回到food = yield,并將’魚肉’賦值給food,生成器函數(shù)恢復(fù)執(zhí)行;直到運(yùn)行到y(tǒng)ield ‘好開心’,程序掛起,返回’好開心’,并print’好開心’

c)接著執(zhí)行print(miao.send(‘骨頭’)),回到y(tǒng)ield ‘好開心’,這時(shí)沒有變量接收參數(shù)’骨頭’,生成器函數(shù)恢復(fù)執(zhí)行;直到food = yield,程序掛起,返回None,并print None

d)接著執(zhí)行print(miao.send(‘雞肉’)),回到food = yield,并將’雞肉’賦值給food,生成器函數(shù)恢復(fù)執(zhí)行;直到運(yùn)行到y(tǒng)ield’不開心,人家要吃魚肉啦’,程序掛起,返回’不開心,人家要吃魚肉啦’,并print ‘不開心,人家要吃魚肉啦’

大功告成,那我們優(yōu)化一下代碼:

def cat():msg = '我是一只hello kitty'while True:food = yield msgif food == '魚肉':msg = '好開心'else:msg = '不開心,人家要吃魚啦'miao = cat()
print(miao.__next__())
print(miao.send('魚肉'))
print(miao.send('雞肉'))

我們再看一個(gè)更實(shí)用的例子,一個(gè)計(jì)數(shù)器。

def counter(start_at = 0):count = start_atwhile True:val = yield countif val is not None:count = valelse:count += 1count = counter(5)
print(count.__next__())
print(count.send(0))

結(jié)果為5,0而不是5,6的原因:

①執(zhí)行print(count.next()),程序運(yùn)行到val = yield count(第一個(gè)yield語句)后掛起,然后返回yield后面的值,所以結(jié)果為5。

②執(zhí)行print(count.send(0)),程序恢復(fù)到掛起點(diǎn)val = yield count,將send的參數(shù)0賦值給接受變量val,然后繼續(xù)執(zhí)行下面的語句,由于val=0,所以if val is not None條件為真,count = val,接著又來到y(tǒng)ield語句(val = yield count),此時(shí)程序掛起,返回yield后面的值count=0。

綜上:當(dāng)執(zhí)行next()方法時(shí),程序會(huì)恢復(fù)到掛起點(diǎn),依次執(zhí)行yield語句下面的語句,最后再返回yield后面的值;而不是先返回yield后面的值,再執(zhí)行yield后面的語句。

最后給出一張圖說明Iterable,Iterator,Generator的關(guān)系:
gen2

補(bǔ)充幾個(gè)小例子:

a)使用生成器創(chuàng)建一個(gè)range

def range(n):count = 0while count < n:yield countcount += 1
http://m.risenshineclean.com/news/59680.html

相關(guān)文章:

  • 太原建站模板廠家seo的優(yōu)點(diǎn)
  • 網(wǎng)站建設(shè)分配人員方案汽車網(wǎng)站建設(shè)方案
  • 哪個(gè)網(wǎng)站做照片書最好看深圳競價(jià)排名網(wǎng)絡(luò)推廣
  • 內(nèi)容展示類網(wǎng)站企業(yè)品牌推廣方案
  • wordpress主題推薦深圳seo網(wǎng)站推廣方案
  • 廣告公司企業(yè)簡介seo 推廣教程
  • 網(wǎng)站設(shè)計(jì)一般包括什么免費(fèi)的api接口網(wǎng)站
  • 江門網(wǎng)站建設(shè)推廣關(guān)鍵詞優(yōu)化seo多少錢一年
  • 網(wǎng)站開發(fā)公司會(huì)計(jì)科目中小企業(yè)網(wǎng)絡(luò)營銷現(xiàn)狀
  • 電商平臺圖片素材seo平臺是什么意思
  • 沈陽世紀(jì)興網(wǎng)站制作泰州seo網(wǎng)絡(luò)公司
  • 零代碼建站平臺免費(fèi)推廣網(wǎng)站視頻
  • 介紹做ppt高大上圖表的網(wǎng)站西安網(wǎng)站搭建
  • top后綴做網(wǎng)站好不好互聯(lián)網(wǎng)公司排名
  • 施工企業(yè)安全生產(chǎn)責(zé)任制度seo教程網(wǎng)站優(yōu)化
  • 印度喜歡用什么框架做外貿(mào)網(wǎng)站南京網(wǎng)站設(shè)計(jì)
  • 百度網(wǎng)站推廣費(fèi)用多少錢福建網(wǎng)站建設(shè)制作
  • 徐州手機(jī)網(wǎng)站建設(shè)公司哪家好免費(fèi)網(wǎng)絡(luò)推廣渠道
  • 小城天長網(wǎng)站建設(shè)seo站長工具 論壇
  • 關(guān)于推進(jìn)政府網(wǎng)站集約化建設(shè)的通知聊城seo
  • 個(gè)人可以做外貿(mào)網(wǎng)站嗎成都百度seo優(yōu)化公司
  • 東莞中堂網(wǎng)站建設(shè)指數(shù)網(wǎng)站
  • 網(wǎng)絡(luò)運(yùn)維需要懂什么技術(shù)武漢seo報(bào)價(jià)
  • 大嶺山鎮(zhèn)網(wǎng)站建設(shè)公司新品牌推廣策略
  • 百度大數(shù)據(jù)官網(wǎng)入口seo網(wǎng)站關(guān)鍵詞快速排名
  • wordpress 頁面二維碼徐州seo培訓(xùn)
  • wordpress案例分析梅州seo
  • 保險(xiǎn)網(wǎng)站有哪些谷歌官方seo入門指南
  • 手機(jī)上如何做mv視頻網(wǎng)站網(wǎng)上接單平臺
  • WordPress重力表單注冊石家莊網(wǎng)絡(luò)seo推廣