迭代器
一山孔、迭代的概念
迭代器即迭代的工具,那什么是迭代呢荷憋?
迭代是一個重復(fù)的過程台颠。每一次重復(fù)即一次迭代,并且每次迭代的結(jié)果都是下一次迭代的初始值
二勒庄、為何要有迭代你串前,什么是可迭代對象瘫里,什么是迭代器對象?
1酪呻、為何要有迭代器减宣?
對于序列類型:字符串,列表玩荠,元組漆腌,我們可以通過使用索引的方式取出其包含的元素,但是對于字典阶冈,集合闷尿,文件等類型是沒有索引的,若還想取出其內(nèi)部包含的元素女坑,則必須找出一種不依賴于索引的迭代方式填具,這就是迭代器
2、什么是可迭代對象匆骗?
可迭代對象是內(nèi)置有__iter__方法對象劳景,即obj.__iter__,如:
'hello'.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{'a':1}.__iter__
{'a','b'}.__iter__
open('a.txt').__iter__
######3.什么是迭代器對象?
可迭代對象執(zhí)行ojb.__iter__()得到的結(jié)果就是迭代器對象
而迭代器對象值得是內(nèi)置有__iter__和__next__方法的對象碉就。
文件類型是迭代器對象
open('a.txt').__iter__()
open('a.txt').__next__()
注意:迭代器對象一定是可迭代對象盟广,而可迭代對象不一定是迭代器對象。
迭代器對象的使用
dic={'a':1,'b':2,'c':3}
iter_dic=dic.__iter__() #得到迭代器對象瓮钥,迭代器對象即有__iter__又有__next__筋量,但是:迭代器.__iter__()得到的仍然是迭代器本身
iter_dic.__iter__() is iter_dic #True
print(iter_dic.__next__()) #等同于next(iter_dic)
print(iter_dic.__next__()) #等同于next(iter_dic)
print(iter_dic.__next__()) #等同于next(iter_dic)
# print(iter_dic.__next__()) #拋出異常StopIteration,或者說結(jié)束標(biāo)志
#有了迭代器碉熄,我們就可以不依賴索引迭代取值了
iter_dic=dic.__iter__()
while 1:
try:
k=next(iter_dic)
print(dic[k])
except StopIteration:
break
for 循環(huán)
基于for循環(huán)桨武,我們可以完全不再依賴索引去取值了
dic = {'a':1,'b':2,'c':3}
for k in dic:
print(dic[k])
for 循環(huán)的工作原理:
1、執(zhí)行in后對象的dic.__iter__()方法锈津,得到一個迭代器對象 iter_dic
2呀酸、執(zhí)行next(iter_dic),將得到的值賦給k,然后執(zhí)行循環(huán)體代碼
3琼梆、重復(fù)過程2性誉,知道捕捉到異常StopIteration,結(jié)束循環(huán)
####迭代器優(yōu)缺點
優(yōu)點:
-提供一種統(tǒng)一的叮叹,不依賴于索引的迭代方式
-惰性計算艾栋,節(jié)省內(nèi)存
缺點:
-無法獲取長度(只有在next完畢后才能知道到底有幾個值)
-一次性的,只能往后走蛉顽,不能往前進
#生成器
####什么是生成器
只要函數(shù)內(nèi)部包含有yield關(guān)鍵字蝗砾,那么函數(shù)名()的到的結(jié)果就是生成器,并且不會執(zhí)行函數(shù)內(nèi)部代碼
def func():
print('====>first')
yield 1
print('====>second')
yield 2
print('====>third')
yield 3
print('====>end')
g=func()
print(g) #<generator object func at 0x0000000002184360>
生成器應(yīng)用(send)
def eater(name):
print('%s is about to eat'%name)
food_list = []
while 1:
food = yield food_list
print('%s has consumed %s'%(name,food))
food_list.append(food)
g = eater('egon')
# next(g)
g.send(None) ###必須先send一個None
g.send('banana')
g.send('apple')
g.send('watermelon')
g.send('peach')
g.send('papaya')
g.send('pear')
在執(zhí)行g(shù).next()時,Python首先會執(zhí)行g(shù)enerator()方法的yield 1 語句悼粮,由于是一個yield語句闲勺,因此此方法的執(zhí)行過程被掛起,而next方法的返回值為yield關(guān)鍵字后面表達(dá)式的值扣猫,即為1菜循。
當(dāng)調(diào)用g.send(2)方法時,Python首先會恢復(fù)generator方法的運行環(huán)境申尤。同時癌幕,將表達(dá)式(yield 1 )的返回值定義為send方法的參數(shù)的值,即為2昧穿。這樣勺远,接下來value=yield 1這一賦值語句會將value的值設(shè)置為2,繼續(xù)運行會遇到y(tǒng)ield value語句时鸵。因此胶逢,generator的方法會再次被掛起,同時饰潜,send方法的返回值也是yield關(guān)鍵字后面的表達(dá)式初坠,也是value的值,即為2.
當(dāng)調(diào)用send(3)的方法原理同上彭雾,但是generator的方法已經(jīng)執(zhí)行完畢碟刺,因此拋出StopIteration異常。
總體來說冠跷,send方法和next方法的唯一區(qū)別是執(zhí)行send方法會首先把上一次yield語句的返回值通過send的參數(shù)設(shè)定南誊,從而實現(xiàn)與生成器方法的交互身诺。但需要注意的是蜜托,在一個生成器沒有執(zhí)行next方法之前,由于沒有yield語句被掛起霉赡,所以執(zhí)行send方法會報錯橄务,所以可以先send(None).
經(jīng)典面試題
面向過程編程
定義:
面向過程編程的核心是過程二字,過程就是解決問題的步驟穴亏,即先干什么再干什么
基于面向過程設(shè)計程序就好比在設(shè)計一條流水線蜂挪,是一種機械式的思維方式
優(yōu)點:復(fù)雜的問題流程化,進而簡單化
缺點:耦合性強嗓化,因而可擴展性差棠涮,牽一發(fā)而動全身