DAY 6. 生成式,迭代器,生成器
6.1 生成式
6.1.1 列表生成式
list = [index for index in range(10)]
6.1.2 字典生成式
dict = {'zhangsan': 10,'lisi': 12,'wangwu': 18
}
# 實現鍵值互換
dict = {k:v for v,k in dict.items() if k >= 12}
6.1.3 集合生成式
# 100以內的質數
set = {i for i in range(100) if i % 2 != 0}
6.2 生成器
生成式會創建一個列表(字典或集合),但無論是字典,列表還是集合,都不能保存一個無限長的序列,比如說全體自然數,當然我們一般不會用到這種序列,但哪怕是萬位的序列,保存為列表或集合也是很占用空間的,加上一般情況下我們對一個序列的操作是一次性的,根本不需要保存,那有沒有一種辦法只有我們需要時才給我們數據,我們不需要時程序只保留“算法”呢?這就用到了生成器
創建生成器有兩種辦法,一種是類似于推導式,把列表推導式的中括號改為小括號就行,會返回一個生成器對象,可以使用next()或for循環遍歷
t = (i for i in range(100) if i % 2 == 0)
for i in t:print(i)
舉個栗子,斐波那契數列,每一項是前兩項之和
一般情況
feibo = [1, 1]
for i in range(2,10000):feibo.append(feibo[i - 1] + feibo[i - 2])
print(feibo)
我們要做的只是要打印出來而已,沒必要保存這么大的數組,這時我們可以用生成器
def feb(f, s, max):i = 0while i < max:f, s = s, f + si += 1yield sfor i in feb(1, 1, 100):print(i)
生成器長得和函數一樣,只不過return 變成了yield ,每當運行到yield后,程序就會阻塞,只有在調用該生成器的next()方法時才會從上次暫停的地方繼續
def Demo():print(1)yield 1print(2)yield 2print(3)yield 3demo = Demo()
next(demo)
next(demo)
next(demo)
next(demo)# 1
# 2
# 3
# Traceback (most recent call last):
# File "E:/xxxx/DAY6_1.py", line 45, in <module>
# next(demo)
# StopIteration
當超出生成器范圍時會拋出StopIteration異常,我們一般也不會使用next,for就是捕捉StopIteration異常遍歷生成器的
for i in Demo():i# 等價于while(True):try:next(demo)except StopIteration:break
6.3 迭代器
6.3.1 可迭代對象
可以直接作用于for循環的對象統稱為可迭代對象:Iterable,主要有兩類,列表,元組,字典,集合等數據類型和生成器,可以使用isinstance()判斷一個對象是否是Iterable對象。
6.3.2 迭代器
可以被next()函數調用并不斷返回下一個值的對象稱為迭代器:Iterator。可以使用isinstance()判斷一個對象是否是Iterator對象
生成器都是Iterator對象,但list、dict、str雖然是Iterable,卻不是Iterator。把list、dict、str等Iterable變成Iterator可以使用iter()函數
你可能會問,為什么list、dict、str等數據類型不是Iterator?
這是因為Python的Iterator對象表示的是一個數據流,Iterator對象可以被next()函數調用并不斷返回下一個數據,直到沒有數據時拋出StopIteration錯誤。可以把這個數據流看做是一個有序序列,但我們卻不能提前知道序列的長度,只能不斷通過next()函數實現按需計算下一個數據,所以Iterator的計算是惰性的,只有在需要返回下一個數據時它才會計算。
Iterator甚至可以表示一個無限大的數據流,例如全體自然數。而使用list是永遠不可能存儲全體自然數的。
6.4 總結
- 生成式
生成式 | 語法 |
---|---|
列表生成式 | L = [i for i in range(100) if i % 2 ==0] |
字典生成式 | k:v for k, v in dict.items() if k < 10 |
集合生成式 | S = {i for i in range(100) if i % 2 ==0} |
- 生成器
創建:
生成式方式和生成器函數
讀取:
next()或for
- 迭代器
可迭代對象 | 能被for直接作用的對象 |
---|---|
迭代器 | 能用next()執行的可迭代對象 |
參考文章:
GitHub python面試題
廖雪峰的官方網站
python 生成器和迭代器有這篇就夠了