Python全棧學習筆記day 13:迭代器、生成器
阿新 • • 發佈:2018-11-02
一、迭代器
字串、列表、元組、字典、集合都可以被for迴圈,說明他們都是可迭代的。
print(dir([])) #告訴我列表擁有的所有方法 ret = set(dir([]))&set(dir({}))&set(dir(''))&set(dir(range(10))) print(ret) #iterable print('__iter__' in dir(int)) print('__iter__' in dir(bool)) print('__iter__' in dir(list)) print('__iter__' in dir(dict)) print('__iter__' in dir(set)) print('__iter__' in dir(tuple)) print('__iter__' in dir(enumerate([]))) print('__iter__' in dir(range(1))) #輸出: ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] {'__str__', '__hash__', '__subclasshook__', '__ge__', '__len__', '__reduce_ex__', '__ne__', '__new__', '__getitem__', '__doc__', '__repr__', '__le__', '__reduce__', '__class__', '__delattr__', '__iter__', '__contains__', '__dir__', '__init__', '__eq__', '__init_subclass__', '__format__', '__getattribute__', '__gt__', '__sizeof__', '__lt__', '__setattr__'} False False True True True True True True
由以上可以得知:
只要是能被for迴圈的資料型別 就一定擁有 __iter__ 方法
print([].__iter__())
#輸出
<list_iterator object at 0x00C2AE30>
一個列表執行了__iter__()之後的返回值就是一個迭代器
print(dir([])) print(dir([].__iter__())) print(set(dir([].__iter__())) - set(dir([]))) 連結串列迭代器方法的集合 - 連結串列方法的集合 =連結串列迭代器有的方法而連結串列沒有的 輸出: ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__length_hint__', '__lt__', '__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__'] {'__next__', '__length_hint__', '__setstate__'}
重點學習:{'__next__', '__length_hint__'}
print([1,'a','bbb'].__iter__().__length_hint__())
輸出:3
.__length_hint__() 返回元素個數
l = [1,2,3] iterator = l.__iter__() print(iterator.__next__()) print(iterator.__next__()) print(iterator.__next__()) print(iterator.__next__()) 輸出: 1 2 3 StopIteration :報錯的意思,原因是連結串列中只有3個元素,第四次迭代時已經沒元素了,所以報錯
總結:
Iterable 可迭代的 -- > __iter__ 只要含有__iter__方法的都是可迭代的
[].__iter__() 迭代器 -- > __next__ 通過next就可以從迭代器中一個一個的取值
只要含有__iter__方法的都是可迭代的 —— 可迭代協議
迭代器協議 : 內部含有__next__和__iter__方法的就是迭代器
可以被for迴圈的都是可迭代的
# 可迭代的內部都有__iter__方法
# 只要是迭代器 一定可迭代
# 可迭代的.__iter__()方法就可以得到一個迭代器
# 迭代器中的__next__()方法可以一個一個的獲取值
for
只有 是可迭代物件的時候 才能用for
當我們遇到一個新的變數,不確定能不能for迴圈的時候,就判斷它是否可迭代
迭代器的好處:
# 從容器型別中一個一個的取值,會把所有的值都取到。
# 節省記憶體空間
#迭代器並不會在記憶體中再佔用一大塊記憶體,
# 而是隨著迴圈 每次生成一個
# 每次next每次給我一個
二、生成器
1、只要含有yield關鍵字的函式都是生成器函式 yield不能和return共用且需要寫在函式內
def generator():
print(1)
yield 'a'
#生成器函式 : 執行之後會得到一個生成器作為返回值
ret = generator()
print(ret)
print(ret.__next__())
輸出:
<generator object generator at 0x00914DF0>
1
a
2、yield會結束本次迭代。並且在一個迭代器中迭代時,下一次迭代是挨著上一次迭代的位置迭代的
栗子:
def generator():
print(1)
yield 'a'
print(2)
yield 'b'
yield 'c'
g = generator()
ret = g.__next__()
print(ret)
輸出:
1
a
def generator():
print(1)
yield 'a'
print(2)
yield 'b'
yield 'c'
g = generator()
ret = g.__next__()
print(ret)
ret = g.__next__()
print(ret)
輸出:
1
a
2
b
def generator():
print(1)
yield 'a'
print(2)
yield 'b'
yield 'c'
g = generator()
ret = g.__next__()
print(ret)
ret = g.__next__()
print(ret)
ret = g.__next__()
print(ret)
輸出:
1
a
2
b
c
三、監聽檔案輸入的例子
def tail(filename):
f = open(filename,encoding='utf-8')
while True:
line = f.readline()
if line.strip():
yield line.strip()
g = tail('file')
for i in g:
if 'python' in i:
print('***',i)