# 生成器函數
# 只要含有 yield 關鍵字的函數都是生成器函數
# yield 不能和 return 共用且須要寫在函數內
# 生成器函數:執行以後會獲得一個生成器做爲返回值
# 生成器既含有 __next__ 方法,也含有 __iter__ 方法,因此生成器也是一個迭代器,能夠使用 __next__ 方法獲取下一個值,也能夠經過 for 循環取值
# yield和return同樣,均可以返回一個值,可是 return 在返回值以後就直接結束一個函數,而 yield 不會
def generator(): '''含有yield,它是一個生成器函數''' print(1) yield 'a' ret = generator() print(ret) print(ret.__next__()) ''' <generator object generator at 0x02FCF8D0> 1 a '''
# 若是我想生成2000000個哇哈哈,用生成器,每生成一個,就返回一個,這樣就不會出現內存不足的問題
def wahaha(): for i in range(2000000): yield '哇哈哈%s' % i g = wahaha() for i in g: print(i)
# send 獲取下一個值的效果和 next 基本一致
# 只是在獲取下一個值的時候,給上一個 yield 的位置傳遞一個數據
# 使用 send 的注意事項
# 第一次使用生成器的時候 是用 next 獲取下一個值
# 最後一個 yield 不能接受外部的值
def generator(): print(123) content = yield 1 print('=======', content) print(456) arg = yield 2 g = generator() ret = g.__next__() print('***', ret) ret = g.send('hello') # send的效果和next同樣 print('***', ret) ''' 123 *** 1 ======= hello 456 *** 2 '''
# 獲取移動平均值
# 10 20 30 10
# 10 15 20 17.5
# avg = sum/count
def average(): sum = 0 count = 0 avg = 0 while True: num = yield avg sum += num # 10 count += 1 # 1 avg = sum/count avg_g = average() avg_g.__next__() avg1 = avg_g.send(10) avg1 = avg_g.send(20) avg1 = avg_g.send(30) print(avg1)
# 預激生成器的裝飾器
def init(func): # 裝飾器 def inner(*args,**kwargs): g = func(*args,**kwargs) # g = average() g.__next__() return g return inner @init def average(): sum = 0 count = 0 avg = 0 while True: num = yield avg sum += num # 10 count += 1 # 1 avg = sum/count avg_g = average() # ===> inner ret = avg_g.send(10) print(ret) ret = avg_g.send(20) print(ret)
# python 3 新特性
# python 2 # def generator(): # a = 'abcde' # b = '12345' # for i in a: # yield i # for i in b: # yield i # python 3 def generator(): a = 'abcde' b = '12345' yield from a yield from b g = generator() for i in g: print(i) ''' a b c d e 1 2 3 4 5 '''
# 生成器表達式python
# 列表推導式 print([i*i for i in range(10)]) # 生成器表達式 print(i for i in range(10)) ''' [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] <generator object <genexpr> at 0x0120FAB0> '''
# 生成器面試題面試
# 面試題1函數
def demo(): for i in range(4): yield i # 生成器都是惰性執行的,只有要它執行的時候它纔會去執行 g = demo() # 生成器對象 g1 = (i for i in g) g2 = (i for i in g1) print(list(g1)) # list(g1)把g1當中全部的內容取出來 print(list(g2)) # g1執行完以後已經空了,因此list(g2)爲空列表 ''' [0, 1, 2, 3] [] '''
# 面試題2spa
def add(n, i): return n+i def test(): for i in range(4): yield i g = test() for n in [1, 10]: g = (add(n, i) for i in g) # 從上到下,一直到這裏,生成器都沒有取過值 '''至關於 n = 1 g = (add(n, i) for i in g) n = 10 g = (add(n, i) for i in (add(n, i) for i in test())) 這裏,n = 10,而不是 n = 1,既 g = (add(10, i) for i in (add(10, i) for i in [0, 1, 2, 3])) 因此,最後結果爲 [20, 21, 22, 23] ''' print(list(g)) # 在這裏,生成器纔開始取值 # [20, 21, 22, 23]