可迭代對象:內部含有__inter__的python
可迭代對象不能取值,由於內部沒有__next__()方法app
可迭代對象------>迭代器:ssh
boj.__iter__()或者inter(obj)ide
實現的原理相似於往彈匣裏面裝子彈,而後一個一個往外發射函數
經過__iter__()來獲取到迭代器spa
1 stes = {1, 2, 3, 4, 5, 67, 7} 2 print(stes.__dir__()) 3 s = stes.__iter__() 4 print(s)
打印結果code
1 ['__repr__', '__hash__', '__getattribute__', '__lt__', '__le__', '__eq__', '__ne__', '__gt__', '__ge__', '__iter__', '__init__', '__sub__', '__rsub__', '__and__', '__rand__', '__xor__', '__rxor__', '__or__', '__ror__', '__isub__', '__iand__', '__ixor__', '__ior__', '__len__', '__contains__', '__new__', 'add', 'clear', 'copy', 'discard', 'difference', 'difference_update', 'intersection', 'intersection_update', 'isdisjoint', 'issubset', 'issuperset', 'pop', '__reduce__', 'remove', '__sizeof__', 'symmetric_difference', 'symmetric_difference_update', 'union', 'update', '__doc__', '__str__', '__setattr__', '__delattr__', '__reduce_ex__', '__subclasshook__', '__init_subclass__', '__format__', '__dir__', '__class__'] 2 <set_iterator object at 0x0000000001EF1480>
經過__next__()來拿到元素,一次只能拿一個,若是最後一個元素以後繼續使用__next__(),會報錯:StopIterationorm
1 stes = {1, 2, 3, 4, 5, 67, 7} 2 s = stes.__iter__() 3 print(s.__next__()) 4 print(s.__next__()) 5 print(s.__next__()) 6 print(s.__next__()) 7 print(s.__next__()) 8 print(s.__next__()) 9 print(s.__next__()) 10 print(s.__next__())
打印結果爲:對象
1 1 2 2 3 3 4 4 5 5 6 67 7 7 8 Traceback (most recent call last): 9 File "C:/Python/Module/regex_test.py", line 53, in <module> 10 print(s.__next__()) 11 StopIteration
判斷是否爲迭代器:blog
1.經過__iter__(),__next__()是否在obj.__dir__()
1 with open('01','w', encoding='utf-8') as f: 2 print('__iter__' in dir(f)) 3 print('__next__' in dir(f)) 4 """ 5 打印結果: 6 True 7 True 8 說明文件句柄自己是一個迭代器 9 """
2.經過collections模塊中的Iterable來判斷
1 from collections import Iterable 2 from collections import Iterator 3 4 l = [1,2,3,4] 5 print(isinstance(l, Iterable)) # 判斷是否爲可迭代對象 6 print(isinstance(l, list)) 7 8 9 """ 10 打印結果: 11 True 12 True 13 """ 14 15 l = [1,2,3,4] 16 print(isinstance(l, Iterable)) 17 print(isinstance(l, Iterator)) 18 print(isinstance(l, list)) 19 20 """ 21 打印結果: 22 True 23 False 24 True 25 """
生成器實質就是迭代器,在python中有三種方式來獲取生成器:
1. 經過生成器函數
2. 經過各類推導式來實現來生成器
3. 經過數據的轉換也能夠獲取生成器
生成器是咱們本身用Python代碼寫的迭代器:
1 def gener(): 2 print(111) 3 yield 222 4 print(333) 5 yield 444 6 print(555) 7 yield 666 8 print(777) 9 yield 888 10 11 12 gen = gener() 13 print(gen) 14 15 # 打印結果爲:<generator object gener at 0x0000000001E74D00>
生成器函數和普通的函數的區別就是把return換成了yield
yield 和return區別
1. 若是函數中包含了yield, 這個函數是一個生成器函數. 執行函數的時候是: 生成器
2. 生成器執行__next__(). 執行到下一個yield
3. yield的做用和return基本相同. 可是,只負責返回. 不會結束函數
4. return,結束函數.
經過obj__next__()方法取值:
1 def gener(): 2 print(111) 3 yield 222 4 print(333) 5 yield 444 6 print(555) 7 yield 666 8 print(777) 9 yield 888 10 11 12 gen = gener() 13 print(gen) 14 ret = gen.__next__() # 這裏的ret至關於執行函數,直行道yield是返回yield的返回值 15 print(ret) 16 ret1 = gen.__next__() 17 print(ret1) 18 ret2 = gen.__next__() 19 print(ret2) 20 ret3 = gen.__next__() 21 print(ret3) 22 23 """ 24 打印結果: 25 <generator object gener at 0x0000000000814D00> 26 111 27 222 28 333 29 444 30 555 31 666 32 777 33 888 34 """
生成器還能夠經過send()方法進行取值個傳值,不過使用send方法時要注意的是:
1.第一個yield必須經過__next__()方法取得
2.最後一個yield不能經過send()方法傳值.
1 def gener(): 2 print(111) 3 a = yield 222 4 print(a) 5 print(333) 6 b = yield 444 7 print(b) 8 print(555) 9 c = yield 666 10 print(c) 11 print(777) 12 yield 888 13 14 15 gen = gener() 16 print(gen) 17 ret = gen.__next__() 18 print(ret) 19 ret1 = gen.send('<<>>') 20 print(ret1) 21 ret2 = gen.send('<<>>') 22 print(ret2) 23 ret3 = gen.send('<<>>') 24 print(ret3) 25 26 """ 27 打印結果: 28 <generator object gener at 0x0000000001DD4D00> 29 111 30 222 31 <<>> 32 333 33 444 34 <<>> 35 555 36 666 37 <<>> 38 777 39 888 40 """
使用send()方法時要注意的是要傳參,否則會報錯
send和__next__() 區別:
send能夠給上一個yield 的位置傳遞值 , 第一個必須用__next__()
__next__() 不能傳值
須要一個列表,裏面包含1到13的數字,第一反應是:
1 l = [] 2 3 for i in range(1, 14): 4 l.append(i) 5 print(l) 6 # 打印結果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
咱們來看這樣一段代碼:
1 l = [ i for i in range(1,14)] 2 print(l) 3 4 #打印結果:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
有這樣一個需求,經過列表推導式來篩選憨厚兩個e的名字:
1 names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'], 2 ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] 3 name2 = [name for i in names for name in i if name.count('e') == 2] 4 print(name2) 5 6 # 打印結果:['Jefferson', 'Wesley', 'Steven', 'Jennifer']
l = [變量(加工後的變量) for 變量 in iterable] 循環模式
l = [變量(加工後的變量) for 變量 in iterable if 條件] 篩選模式
相似於真樣的式子被成爲列表推導式.
優勢:
1,節省代碼,一行搞定.
2,看着高大上.
缺點:
很差排錯.
總體:
凡是用列表推導式構造的列表對象,用其餘方式均可構建.,很是複雜的列表,列表推導式是構建不出的,
列表推導式比較有魔性.
生成器表達式和列表推導式基本同樣,惟一的區別就是把列表推推導式的方括號變成圓括號:
1 l = ( i for i in range(1,14)) 2 print(l) 3 4 #打印結果:<generator object <genexpr> at 0x0000000001F24D00>
一樣的也有兩種模式:
循環模式和篩選模式