1.迭代和可迭代協(xié)議
????1)什么叫迭代
????????for?i?in?[1,2,3,4]:?
????????????print(i)
????????結(jié)果:
????????????1
????????????2
????????????3
????????????4
????????for?i?in?1234
????????????print(i)?
????????結(jié)果:
????????Traceback (most recent call last):
??????????File?"test.py", line?4,?in?
????????????for?i?in?1234:
????????TypeError:?'int'?object?is?not?iterable?
????????錯誤說,我們的1234不可迭代荚守。上面的卻可以楷兽。
????????那么大膽推測,如果可以迭代,就應(yīng)該可以被for循環(huán)哥谷。
????????我們知道雌芽,字符串、列表败砂、元祖赌渣、集合、字典都可以for循環(huán)
????????說明他們都是可迭代的昌犹。
????????那么正確的路子應(yīng)該是什么樣的呢坚芜,總不能憑空想象。
????????from?collections?import?Iterable?
????????s?=?'1234'
????????l?=?[1,2,3,4]?
????????t?=?(1,2,3,4)?
????????d?=?{1:2,3:4}?
????????s?=?{1,2,3,4}
????????print(isinstance(a,Iterable))#Ture?
????????print(isinstance(l,Iterable))#Ture
????????print(isinstance(t,Iterable))#Ture
????????print(isinstance(d,Iterable))#Ture
????????print(isinstance(s,Iterable))#Ture
????????綜上:可以將某個數(shù)據(jù)集內(nèi)的數(shù)據(jù)“一個挨一個的取出來”斜姥,就叫做迭代鸿竖。
????2)可迭代協(xié)議
????????可以被迭代滿足的要求就叫做可迭代協(xié)議。
????????可迭代協(xié)議铸敏;就是內(nèi)部實現(xiàn)了 __iter__() 方法
????????驗證:
????????????print(dir([1,2]))
????????????print(dir((1,2)))
????????????print(dir({1:2}))
????????????print(dir({1,2}))
????????總結(jié):
????????????可以被for循環(huán)的都是可迭代的缚忧,想要可迭代,內(nèi)部必須有一個
????????????__iter__() 方法搞坝。
????????????接著分析搔谴,這個 __iter__()做了什么事情?
????????????print([1,2].__iter__())
????????????結(jié)果
????????????
????????????這里的iterator就是迭代器桩撮。
2.迭代器
????可迭代后又一難題出現(xiàn)了敦第,什么叫“迭代器”?
????'''
????dir([1,2].__iter__())是列表迭代器中實現(xiàn)的所有方法店量,
????dir([1,2])是列表中實現(xiàn)的所有方法,都是以列表的形式返
????回給我們的芜果,為了看的更清楚,我們分別把他們轉(zhuǎn)換成集合融师,
????然后取差集右钾。
????'''
????#print(dir([1,2].__iter__()))
????#print(dir([1,2]))
????print(set(dir([1,2].__iter__()))-set(dir([1,2])))
????結(jié)果:
????{'__length_hint__',?'__next__',?'__setstate__'}
????我們看到在列表迭代器中多了三個方法,那么這三個方法都是
????干什么的呢?
????????iter_l?=?[1,2,3,4,5,6].__iter__()#列表迭代器
????????#獲取迭代器中元素的長度
????????print(iter_l.__length_hint__())
????????#根據(jù)索引值指定從哪里開始迭代
????????print('*',iter_l.__setstate__(4))
????????#一個一個的取值
????????print('**',iter_l.__next__())
????????print('***',iter_l.__next__())
????????結(jié)果:
????????????6
????????????*?None
????????????**?5
????????????***?6
????這三個方法中舀射,能夠一個一個取值的方法就是 __next__()
????在for循環(huán)中窘茁,就是在內(nèi)部調(diào)用了 __next__() 方法才能取到
????一個一個的值。
????例子:
????????l?=?[1,2,3]
????????l_iter?=?l.__iter__()
????????item?=?l_iter.__next__()
????????print(item)#1
????????item?=?l_iter.__next__()
????????print(item)#2
????????item?=?l_iter.__next__()
????????print(item)#3
????????item?=?l_iter.__next__()
????????print(item)#StopIteration
????????注意:
????????????如果我們一直取脆烟,直到next取到迭代器里已經(jīng)沒有元素了山林,
????????????就會拋出一個StopIteration異常,告訴我們邢羔,列表中已經(jīng)
????????????沒有有效元素了驼抹。
????????????這個時候,我們就要使用異常處理機制來把這個異常處理掉拜鹤。
????????????例子:
????????????????lis?=?['1',?'2',?'3']
????????????????it?=?lis.__iter__()
????????????????while?1:
????????????????????try:
????????????????????????res?=?it.__next__()
????????????????????????print(res)
????????????????????except?StopIteration:
????????????????????????break
????????????????結(jié)果:
????????????????????1
????????????????????2
????????????????????3
????注:
????????迭代器遵循迭代器協(xié)議:必須擁有 __iter__()方法和__next__()方法框冀。
????????# 迭代器的特點:
????????#?? 1. 節(jié)省內(nèi)存
????????#?? 2. 惰性機制
????????#?? 3. 只能往前拿. 不能反著拿
3.判斷對象是迭代器還是可迭代對象
????例子:
????????from?collections?import?Iterator
????????from?collections?import?Iterable
????????print(isinstance(range(10), Iterator))#False
????????print(isinstance(range(10), Iterable))#Ture
????????>>>?from?collections?import?Iterator
????????>>>?isinstance((x?for?x?in?range(10)), Iterator)
????????True
????????>>>?isinstance([], Iterator)
????????False
????????>>>?isinstance({}, Iterator)
????????False
????????>>>?isinstance('abc', Iterator)
????????False
????????>>>?from?collections?import?Iterable
????????>>>?isinstance([], Iterable)
????????True
????????>>>?isinstance({}, Iterable)
????????True
????????>>>?isinstance('abc', Iterable)
????????True
????????>>>?isinstance((x?for?x?in?range(10)), Iterable)
????????True
????????>>>?isinstance(100, Iterable)
????????False