生成器 迭代器理解

2022-09-02 04:21:12 字數 4912 閱讀 4061

def consumer():

r = ''

while true:

n = yield r # 第2步:yield接收,n=none # 第4步:n=1 # 第6步:返回 r="200 ok"; 備註: "n"是收到生產者的資料(賦值給"n"),"r"是返回給生產者的資料.

if not n:

return

print('[消費者] consuming %s...' % n) #第4步:列印 n=1

r = '200 ok' # 第5步:賦值

def produce(c):

# 注意:next(c) 和 c.send(none)是相等的

c.send(none) # 第1步. 喚醒consumer進入到yield

n = 0

while n < 5:

n = n + 1

print('[生產者] producing %s...' % n)

r = c.send(n) # 第3步. 傳送資料"1"給comsumer中的yield # 第7步.收到r="200 ok"

print('[生產者] consumer return: %s' % r) # 列印r值

c.close()

c = consumer()

produce(c)

# yield有3個作用

# 1. 凍結

# 2. 返回資料

# 3. 接收資料

# yield工作過程

# 1. c.send(1)傳值給yield,yield先賦值給n然後向下執行。

# 2. 通過while迴圈再次遇到yield後,則返回yield後面r的值。

1. 有__iter__()方法的物件叫iterable。 如:tuple list dict string set open(file) 

2. 有__next__()和__iter__()方法的物件叫迭代器物件。 如:open(file)

3. 迭代器物件一定是可迭代物件, 而可迭代物件不一定是迭代器物件。

4. 有了迭代器我們可不依賴索引取值了。

#基於for迴圈,我們可以完全不再依賴索引去取值了

dic=

for k in dic:

print(dic[k])

#for迴圈的工作原理

#1:執行in後物件的dic.__iter__()方法,得到乙個迭代器物件iter_dic

#2: 執行next(iter_dic),將得到的值賦值給k,然後執行迴圈體**

#3: 重複過程2,直到捕捉到異常stopiteration,結束迴圈

#優點:

- 提供一種統一的、不依賴於索引的迭代方式

- 惰性計算,節省記憶體

#缺點:

- 無法獲取長度(只有在next完畢才知道到底有幾個值)

- 一次性的,只能往後走,不能往前退

1. 只要函式內部包含有yield關鍵字,那麼函式名()的到的結果就是生成器,並且不會執行函式內部**

2. 生成器就是特殊的迭代器

例:

1、自定義函式模擬range(1,7,2)

2、模擬管道,實現功能:tail -f access.log | grep '404'

#題目一:

def my_range(start,stop,step=1):

while start < stop:

yield start

start+=step

#執行函式得到生成器,本質就是迭代器

obj=my_range(1,7,2) #1 3 5

print(next(obj))

print(next(obj))

print(next(obj))

print(next(obj)) #stopiteration

#應用於for迴圈

for i in my_range(1,7,2):

print(i)

#題目二

import time

def tail(filepath):

with open(filepath,'rb') as f:

f.seek(0,2)

while true:

line=f.readline()

if line:

yield line

else:

time.sleep(0.2)

def grep(pattern,lines):

for line in lines:

line=line.decode('utf-8')

if pattern in line:

yield line

for line in grep('404',tail('access.log')):

print(line,end='')

#測試with open('access.log','a',encoding='utf-8') as f:

f.write('出錯啦404\n')

3、模擬吃飯

#yield關鍵字的另外一種使用形式:表示式形式的yield

def eater(name):

print('%s 準備開始吃飯啦' %name)

food_list=

while true:

food=yield food_list

print('%s 吃了 %s' % (name,food))

g=eater('egon')

g.send(none) #對於表示式形式的yield,在使用時,第一次必須傳none,g.send(none)等同於next(g)

g.send('蒸羊羔')

g.send('蒸鹿茸')

g.send('蒸熊掌')

g.send('燒素鴨')

g.close()

g.send('燒素鵝')

g.send('燒鹿尾')

4、通過裝飾器初始化yield生成器函式

(1)、編寫裝飾器,實現初始化協程函式的功能

(2)、實現功能:grep -rl 'python' /etc

#題目一:

def init(func):

g=func(*args,**kwargs)

next(g)

return g

@init

def eater(name):

print('%s 準備開始吃飯啦' %name)

food_list=

while true:

food=yield food_list

print('%s 吃了 %s' % (name,food))

g=eater('egon')

g.send('蒸羊羔')

#題目二:

#注意:target.send(...)在拿到target的返回值後才算執行結束

import os

def init(func):

g=func(*args,**kwargs)

next(g)

return g

@init

def search(target):

while true:

filepath=yield

g=os.walk(filepath)

for dirname,_,files in g:

for file in files:

abs_path=r'%s\%s' %(dirname,file)

target.send(abs_path)

@init

def opener(target):

while true:

abs_path=yield

with open(abs_path,'rb') as f:

target.send((f,abs_path))

@init

def cat(target):

while true:

f,abs_path=yield

for line in f:

res=target.send((line,abs_path))

if res:

break

@init

def grep(pattern,target):

tag=false

while true:

line,abs_path=yield tag

tag=false

if pattern.encode('utf-8') in line:

target.send(abs_path)

tag=true

@init

def printer():

while true:

abs_path=yield

print(abs_path)

g=search(opener(cat(grep('你好',printer()))))

# g.send(r'e:\cms\aaa\db')

g=search(opener(cat(grep('python',printer()))))

g.send(r'e:\cms\aaa\db')

生成器 迭代器

最近見天一直在看廖大的python教程,卻發現很多基礎看著很簡單,但卻不會應用,歸根結底還是因為理解不到位,故而又將教程學了一遍,並將自己的理解記錄一下,也方便後面查閱。由於沒有相關程式設計基礎,有些理解可能是錯的,敬請批評指正。想深入具體學習廖大部落格請移步廖雪峰的官方 有時候用迴圈生成列表太過繁...

迭代器,生成器

迭代器 生成器 生成器的第1種實現方式 列表生成式改為生成器 python中yield關鍵字 函式中如果有yield,那麼呼叫這個函式的返回值為生成器。當生成器g呼叫next方法,執行函式,知道遇到yield就停止 再執行next,從上一次停止的地方繼續執行 函式中遇return直接退出,不繼續執行...

迭代器 生成器

迭代器 iter 可迭代物件 下乙個元素的值 next 可迭代物件 類中實現 iter 方法 提供迭代器 實現迭代器 import time class mylistiter object 迭代器類 def init self,data self.data data self.index 0 def...