python3之迭代器&生成器


1、迭代器

迭代是Python最強大的功能之一,是訪問集合元素的一種方式。。

迭代器是一個可以記住遍歷的位置的對象。

迭代器對象從集合的第一個元素開始訪問,直到所有的元素被訪問完結束。迭代器只能往前不會后退。

迭代器有兩個基本的方法:iter() 生成迭代器和 next()遍歷迭代器元素。

>>> dil = iter(range(10))  #使用iter方法創建一個迭代器
>>> print(type(dil))    #類型為迭代器
<class 'range_iterator'>
>>> print(dil)
<range_iterator object at 0x7fb9bf466ed0>
>>> l1 = [1,2,3,4,5]
>>> it = iter(l1)    #將列表轉換為迭代器
>>> print(type(it))
<class 'list_iterator'>
>>> print(it)
<list_iterator object at 0x7fb9bf42e9e8>

>>> print(next(it))
1
>>> print(next(it))
2
>>> print(next(it))
3
>>> print(next(it))
4
>>> print(next(it))
5
>>> print(next(it))   #如果迭代器元素到最后沒有了就會報錯
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> for i in it:    #此處因為迭代元素已經到了最后,所以沒有元素輸出
...   print(i,end=" ")
... 

>>> print(next(dil))   #使用next輸出迭代器的下一個元素
0
>>> print(next(dil))
1
>>> print(next(dil))
2
>>> print(next(dil))
3
>>> for i in dil:    #而輸出dil迭代器的元素會接着輸出迭代器的元素,知道最后一個。
...   print(i,end=" ")
... 
4 5 6 7 8 9 >>> 

>>> list = [1,2,3,4,5,6,7,8]
>>> inter1 = list.__iter__()  #遵循迭代器協議,生成可以迭代的對象
>>> print(inter1.__next__())
1
>>> print(inter1.__next__())
2

#集合中使用迭代器
>>> s1 = {'python','java','net','php'}
>>> iter2 = s1.__iter__()
>>> print(iter2)
<set_iterator object at 0x7fb9bf450ea0>
>>> print(iter2.__next__())
java
>>> print(iter2.__next__())
php
>>> print(iter2.__next__())
net
>>> print(iter2.__next__())
python
>>> print(iter2.__next__())

#字典中使用迭代器
>>> dict1 = {'k1':'v1','k2':'v2'}
>>> iter3 = dict1.__iter__()
>>> print(iter3.__next__())   #字典默認迭代的是key值
k1
>>> print(iter3.__next__())
k2

#文件中使用迭代器
>>> with open('test','r') as f1:
...   iter5 = f1.__iter__()
...   print(iter5.__next__(),end = ' ')
...   print(iter5.__next__(),end = ' ')
...   print(iter5.__next__(),end = ' ')
... 
11111   2222
 33333   4444
 55555   6666

2、生成器

在 Python 中,使用了 yield 的函數被稱為生成器(generator)。

跟普通函數不同的是,生成器是一個返回迭代器的函數,只能用於迭代操作,更簡單點理解生成器就是一個迭代器。

在調用生成器運行的過程中,每次遇到 yield 時函數會暫停並保存當前所有的運行信息,返回yield的值。並在下一次執行 next()方法時從當前位置繼續運行。

生成器可以理解為一種數據類型,這種數據類型自動實現了迭代器協議(其他的數據類型需要調用自己內置的__iter__方法),所以生成器就是可迭代對象 

    生成器分類及在python中的表現形式:(Python有兩種不同的方式提供生成器)

    1.生成器函數:常規函數定義,但是,使用yield語句而不是return語句返回結果。yield語句一次返回一個結果,在每個結果中間,掛起函數的狀態,以便下次重它離開的地方繼續執行

    2.生成器表達式:類似於列表推導,但是,生成器返回按需產生結果的一個對象,而不是一次構建一個結果列表

    為何使用生成器之生成器的優點

   Python使用生成器對延遲操作提供了支持。所謂延遲操作,是指在需要的時候才產生結果,而不是立即產生結果。這也是生成器的主要好處。

   生成器小結:

   1.是可迭代對象

   2.實現了延遲計算,省內存啊

   3.生成器本質和其他的數據類型一樣,都是實現了迭代器協議,只不過生成器附加了一個延遲計算省內存的好處

def ite():
    print('hello')
    yield 'test1'
    print('world')
    yield 'test2'
    yield 'test3'
    yield 'test4'

gen = ite()   #生成了一個生成器
print(type(gen))
print(gen.__next__())
print(gen.__next__())
print(gen.__next__())
print(gen.__next__())

<class 'generator'>
hello
test1
world
test2
test3
test4

生成器方法:

close():手動關閉生成器,后面的調用會直接返回Stoplteration異常。

>>> def gen():
...   yield 'hello'
...   yield 'python'
... 
>>> st = gen()
>>> print(st.__next__())
hello
>>> st.close()   #關閉生成器后再顯示元素就拋出異常
>>> print(st.__next__())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

send():生成器函數最大的特點是可以接受外部傳入的一個變量,並根據變量內容計算結果后返回。

def consumer(name):
    print('begin..')
    while True:
        baozi = yield name  #第一次執行時返回name的值,然后將send的值賦值給yield
        print('is you %s' %baozi)  #所以此時baozi的值為1

d = consumer('zhang')
print(d.__next__())
print(d.send(1))
print(d.send(2))
print(d.send(3))
print(d.send(5))

begin..
zhang
is you 1
zhang
is you 2
zhang
is you 3
zhang
is you 5
zhang

throw():用來想生成器函數傳入一個異常,可以結束系統定義的異常,或者自定義的異常。

throw()后直接拋出異常並結束程序,或者消耗掉一個yield,或者在沒有下一個yield的時候直接進行到程序的結尾。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM