1. 程式人生 > >Python全棧學習筆記day 13:迭代器、生成器

Python全棧學習筆記day 13:迭代器、生成器

一、迭代器

字串、列表、元組、字典、集合都可以被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)