一、列表生成器:列表生成式就像是一個廚師,他只會作這n(n爲任意整數)道菜,想吃甚麼作甚麼,不吃不作,不浪費空間;而列表表達式就至關於已經作好的n盤菜,佔用空間。
二、生成器的建立方法:python
注意:生成器在建立的時候已經決定了能計算出值得個數,調用next的個數一旦超過這個值就會報錯併發
第一種:xss
s = (x*2 for x in range(5))
# 生成器的調用方法:next() print(next(s)) # 提取生成器裏面的值,in python2中等價於 s._next_(),next() 一次打印一次
print(next(s))
print(next(s)) # 生成器就是一個可迭代對象(Iterable) for i in s: # 遍歷生成器可迭代對象 print(i) # 打印完一個數以後這個數就被回收,不佔用內存,只佔用被引用值的哪個內存
>>> 0 2 4 6 8函數
運行機制:從0開始,第一次next()時,取出一個數*2輸出,而後每next()一次,取一個數,一直到2,for循環遍歷時,由於前面next()已經取到了數字2的位置,因此從3開始,故輸出爲0 2 4 6 8spa
第二種:code
def fun(): # 注意:生成器對象是fun(),而不是fun print('s') yield 1 print('ss') yield 2 g = fun() print(g) # <generator object fun at 0x000001D54E12A0F8> next(g) # 有返回值,爲yield後的值 next(g)
解釋:程序運行時先執行g = fun(), 執行到第一個next()時,返回到函數中執行具體內容,一直到執行完yield 1 中止,而後繼續下一個next(),再到函數中尋找yield 2 的內容,以此類推。 注意:若是再多一個next(g),就會報錯:StopIteration(中止迭代),由於超過了迭代次數對象
什麼是可迭代對象:內部有 _iter_() 的都是可迭代對象(列表、元組、字典)
blog
def fun(): print('s') yield 1 print('ss') yield 2 for i in fun(): print(i) # yield 有返回值,返回值賦給了i
>>>ip
s
1
ss
2內存
例1:輸出斐波那契數列
def fib(maxs): n, before, after = 0, 0, 1 while n < maxs: print(after) # 從1開始,如打印before則從從0開始 before, after = after, before+after # 先計算後賦值(先右後左) n = n+1 fib(10) # 輸出前10個斐波那契數
注意:before, after = after, before+after 和 下面的兩條語句不等價,緣由見例1對應標註;
before = after
after = before+after
例2:斐波那契數列生成器
def fib(maxs): n, before, after = 0, 0, 1 while n < maxs: yield before before, after = after, before+after # 先計算後賦值(先右後左) n = n+1 g = fib(8) print(g) # 生成器所在的內存地址 # 須要幾個next() 幾回,但最多不能超過8次,不然應修改fib() 裏面的數字 print(next(g)) print(next(g)) print(next(g)) print(next(g))
三、 .send() 方法
def fun(): # fun()是一個生成器對象而不是fun print('qwer') count = yield 1 # 先把yield的值返回,而後把‘xss’賦值給變量count print(count) print('asdf') yield 2 f = fun() # next(f) # 進入函數體 f.send(None) # 等價於next(f)
s = f.send('xss') # 給yield前面的變量賦值 print(s)# s 是yield 2 的返回值
注意:第一次send前若是沒有next,只能傳一個send(None),不然報錯,TypeError: can't send
non-None value to a just-started generator,第一次經過進入send(None) 進入函數以後首先執行
print(),yield返回一個1,再次進入以後就把send()裏面的值傳給count,而後就能夠對count進行操做
例3:yield 僞併發的實現
import time def consumer(name): print("%s準備吃包子!" % name) while True: baozi = yield print("包子[%s]來了,被[%s]吃了!" % (baozi, name)) def producer(name): a1 = consumer('A') a2 = consumer('B') next(a1) next(a2) print("%s準備吃包子了!" % name) for i in range(5): time.sleep(1) print("作了2個包子") a1.send(i) a2.send(i) producer("xiaoss")
>>>
A準備吃包子!
B準備吃包子!
xiaoss準備吃包子了!
作了2個包子
包子[0]來了,被[A]吃了!
包子[0]來了,被[B]吃了!
作了2個包子
包子[1]來了,被[A]吃了!
包子[1]來了,被[B]吃了!
作了2個包子
包子[2]來了,被[A]吃了!
包子[2]來了,被[B]吃了!
作了2個包子
包子[3]來了,被[A]吃了!
包子[3]來了,被[B]吃了!
作了2個包子
包子[4]來了,被[A]吃了!
包子[4]來了,被[B]吃了!
一、什麼是迭代器?
迭代是指能夠用for循環來遍歷
for循環內部三件事: 1.調用可跌代對象的iter方法返回一個可迭代對象
2.不斷調用可迭代對象的next方法
3.處理StopIteration
處理StopIteration的過程以下:
while: try: I = next(list_Iterator) except StopIteration: break
注:生成器都是迭代器,迭代器不必定是生成器
二、知足兩個條件: (1)有iter方法 (2) 有next方法
from collections import Iterable,Iterator # 調用Iterable和Iterator lis = [1, 2, 3, 4] d = iter(lis) # 至關於 l._iter_() print(d) # <list_iterator object at 0x00000206700DC358> print(next(d)) print(next(d)) print(next(d)) print(next(d)) for i in [1, 2, 3, 4]: iter([1, 2, 3, 4]) print(isinstance([1, 2], list)) # 判斷一個字符是否是某個特定的數據類型 isinstance(數據, 數據類型) print(isinstance(lis, Iterable)) # 判斷lis是否是迭代器
>>>
<list_iterator object at 0x000002756B321240>
1
2
3
4
True
True
例1:用迭代找出文檔中最長的行
F = max(len(x.strip()) for x in open('file_1', 'r')) # 文件讀取,找出最長的行 print(F) # 最長行字符的個數