日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

yield表达式形式的应用

發布時間:2025/3/17 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 yield表达式形式的应用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  • 基本格式
  • 如何給yield傳值
  • yield表達式形式的應用
    • 栗子一吃貨函數
    • 栗子二模擬linux中的命令 grep -rl 查找內容 目錄

基本格式

x = yield 把yield的接收值,賦值給x

def foo():while True:x = yield # 函數執行到yield處,暫停,yield后面沒有任何返回值,默認返回yield Noneprint("x's value is ", x) # next執行,打印出x的值,yield 沒有接收任何傳值,默認接收None,并賦值給x,# 然后繼續執行,返回循環體,又執行到yield處,暫停,返回None g = foo() print(next(g)) print(next(g)) # 運行結果如下: # None # x's value is None # None

如何給yield傳值

帶有關鍵字yield的函數的執行結果就是生成器,假設為g, 調用g.send(value)方法,就可以給yield傳值。g.send(None)就是給yield傳None, 相當于沒傳,也就等同于next(g) 的執行效果。
注意,g.send(value) 的傳值方式是基于一個暫停的位置。也就是說生成器函數必須先執行到yield處,暫停在那里,給yield傳值,然后執行next(g)。因此,在使用g.send(value) 給yield傳值前,要進行初始化:next(g) 或者g.send(None)。
我們可以用裝飾器來做生成器的初始化:

def init(g_func): #定義裝飾器函數def wrapper(*args, **kwargs):g = g_func(*args, **kwargs)next(g) # 用next(g)將生成器函數暫停到yield處,以完成初始化return greturn wrapper@init def foo():while True:x = yieldprint("x's value is ",x)g = foo() print(g.send(1)) # 通過裝飾器完成了初始化后,就可以直接給yield傳值了 print(g.send(2)) print(g.send(3)) # 執行結果如下: # x's value is 1 # None # x's value is 2 # None # x's value is 3 # None

yield表達式形式的應用

栗子一:吃貨函數

@init # 用裝飾器來初始化函數 def eater(name):print('{} is ready to eat!'.format(name))food_list = []while True:food = yield food_list # 在暫停處給yield 傳值,yield 得到的值賦值給food(給吃貨上菜)。再次執行到yield 暫停,返回food_listfood_list.append(food)print('{} is eating {}'.format(name, food))e = eater('Seb') # 執行函數,得到一個生成器 print(e.send('meat')) # 給yield傳值并執行函數 print(e.send('fish')) print(e.send('chicken')) # 執行效果如下: # Seb is ready to eat! # Seb is eating meat # ['meat'] # Seb is eating fish # ['meat', 'fish'] # Seb is eating chicken # ['meat', 'fish', 'chicken']

上面這個栗子,我們也可以通過一個函數來專門生產yield需要的值,然后從外部傳給yield,實現程序的協同工作:

@init # 用裝飾器來初始化函數 def eater(name):print('{} is ready to eat!'.format(name))food_list = []while True:food = yield food_list # 在暫停處給yield 傳值,yield 得到的值賦值給food(給吃貨上菜)。再次執行到yield 暫停,返回food_listfood_list.append(food)print('{} is eating {}'.format(name, food))def make_food(target, n):for i in range(n):target.send('food_{}'.format(i)) # target代表一個需要被傳值的生成器e = eater('Seb') # 執行函數,得到一個生成器 make_food(e, 3) # 執行效果如下: # Seb is ready to eat! # Seb is eating food_0 # Seb is eating food_1 # Seb is eating food_2

栗子二:模擬linux中的命令 grep -rl ‘查找內容’ /目錄

遞歸的查找某目錄下的文件夾及文件,只要是文件內含有”查找內容“的,打印出文件路徑。
分析以上需求,有四個步驟:
1. 遞歸的找出文件路徑,結果給下一步
2. 收到路徑,打開文件獲取文件,把文件對象給下一步
3. 收到文件,打開文件遍歷,取出每一行的內容,給下一步
4. 收到一行內容,判斷有沒有”查找內容“,有的話,把文件名給下一步
5. 收到文件名,打印
下面通過5個函數來實現,函數之間傳遞值用target.send(value) ;接收值用var = yield

import os # !!!一個慘痛的教訓,定義一個函數時,千萬不要和系統內置的名字沖突,否則會各種報錯!!! def init(func):"""裝飾器傳入一個生成器函數,對其進行初始化:param g_func: :return: """def wrapper(*args, **kwargs):g = func(*args, **kwargs)next(g)return greturn wrapper@init def search_file(target):while True:dir_path = yieldg = os.walk(dir_path) # os.walk(dir_path)得到的結果是生成器,對這個生成器迭代可以拿到一個個元組。# 每個元組由(當前目錄絕對路徑,當前目錄下的子目錄列表,當前目錄下的文件列表)三個元素構成。# 通過拼接當前目錄路徑和該目錄下的文件,就可以得到每個文件的絕對路徑。for par_dir, _, file_path_list in g: # 迭代,解壓元組的元素,當前目錄的絕對路徑賦值給par_dir,# 文件路徑的集合賦值給file_path_list。不需要的元素丟給 _for file_path in file_path_list:file_path = r'%s\%s'% (par_dir, file_path) # 拼接文件的絕對路徑target.send(file_path) # 把結果發送給需要被傳值的對象@init def open_file(target):while True:file_path = yieldwith open(file_path, encoding='utf-8')as f:target.send((file_path, f))@init def read_file(target):while True:file_path, f = yieldfor line in f:res = target.send((file_path, line)) # 返回值res就是下一個函數的執行的返回值,即tagif res:break@init def grep_file(target, pattern):tag = Falsewhile True:file_path, line = yield tagtag = False # 這里保持False狀態。否則只要過濾成功一次,tag為True, 那么if pattern in line:target.send(file_path)tag = True # 匹配出一個文件內包含查找內容后,更改tag的狀態,令上一個函數停止遍歷該文件,以免發送重復的文件路徑。@init def print_result():while True:file_name = yieldprint(file_name)dir_path = r'D:\testdir' g = search_file(open_file(read_file(grep_file(print_result(), 'a')))) g.send(dir_path) # 函數執行結果如下: # D:\testdir\testa\a.txt # D:\testdir\testa\aa.txt # !!!一個慘痛的教訓,定義一個函數時,千萬不要和系統內置的名字沖突,否則會各種報錯!!!

總結

以上是生活随笔為你收集整理的yield表达式形式的应用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。