python------生成器粗略解讀

'''
  生成器函數:
    只要含有yield關鍵字的函數都是生成器函數,且該關鍵字只能寫在函數裏,並且yield不能與return共用
    特點:
        調用函數之後函數不執行,返回一個生成器
        每次調用__next__方法後會取到一個值,知道取完最後一個,再執行__next__(or next())會報錯
  生成器本質上就是迭代器
  生成器的表現形式:
    生成器函數:生成器函數本質上就是我們自己寫的函數
    生成器表達式

  生成器中取值的幾個方法
    1.next 2.for 3.數據類型的強制轉換(耗內存)
'''

# def generator():
#     print("這是生成器函數1")
#     yield '生成器函數返回值1' # 與return 的作用類似,都可以返回值,但是yield返回值後並不會結束函數
#     print("這是生成器函數2")
#     yield '生成器函數返回值2'
#     print("這是生成器函數3")
#     yield '生成器函數返回值3'
#
# g = generator()  # 返回的是一個生成器對象
# print(g.__next__()) # 通過__next__()函數可以迭代生成器,直到找到下一個yield爲止
# 我們也可以通過for循環來迭代,其實for循環內部就實現了迭代器的方式,用for循環來讀取生成器中的內容時,會全部讀取,而不是一個一個讀取
# for i in g:
#     print("-----"+i)

#------------------------------------------------------------------------------------------------------------------------
# 下面是利用生成器來監聽文件輸入的例子
# def monitor(filename):
#     obj = open(file=filename, encoding='utf-8')
#     while True:
#         line = obj.readline()
#         if line.strip(): # 當讀取的一行不爲空才返回
#             yield line.strip()
#
# g = monitor('filemonitor.txt') # 這裏我們得到一個生成器對象
# # 下面是我們需要監聽的內容,假設當文件被寫入了含有python的內容時,我們可以將這行內容打印出來
# # 注意:在向文件寫入完內容後必須保存才行。
# for i in g:
#     if 'python' in i:
#         print("包含python的一行是:",i)

#------------------------------------------------------------------------------------------------------------------------
# 生成器中send的使用形式
# def generator():
#     print("這是生成器函數1")
#     content = yield '生成器函數返回值1' # 用content接收send過來的值
#     print("接收返回的值:",content)
#     print('xxxxxxxxxxxxxxxxxx')
#     yield '生成器返回值2'
#
# g = generator()  # 返回的是一個生成器對象
# print(g.__next__()) # 通過__next__()函數可以迭代生成器,直到找到下一個yield爲止
# ret = g.send("接收成功")
# print('---->',ret)
# 打印如下 這是生成器函數1
# 生成器函數返回值1
# 接收返回的值: 接收成功
# xxxxxxxxxxxxxxxxxx
# ----> 生成器返回值2
'''
send 獲取下一個值的效果和next基本一致
只是在獲取下一個值的時候,給上一個返回值的位置(即上一個yield的位置)傳遞一個數據
    使用send的注意事項
        在第一次使用生成器時,必須先使用__next__獲取下一個值
        最後一個yield不能接收外部的值
'''
#------------------------------------------------------------------------------------------------------------------------
# 生成器函數進階(使用一個計算平均數的例子來演示----輸入一個數,計算一次平均數)
#
# def average():
#     sum = 0
#     count = 0
#     avg = 0
#     while True:
#         num = yield avg
#         sum += num
#         count += 1
#         avg = sum / count
#
# avg_g = average()
# print(next(avg_g)) # 返回0
# print(avg_g.send(10)) # 返回10
# print(avg_g.send(20)) # 返回15
# 上述的就是一個利用生成器函數不斷計算輸入數的平均數的例子,不過在上述代碼中,我們要先調用一個__next__(或者next()方法)方法,在能再調用send
# 對於這個問題,下面我們可以使用裝飾器來解決
# 下面就是預激生成器的裝飾器
# def init(function):  # 在調用被裝飾生成函數的時候首先用next激活生成器
#     def inner(*args, **kwargs):
#         g = function(*args, **kwargs)
#         next(g)
#         return g
#     return inner
#
# @init
# def average():
#     sum = 0
#     count = 0
#     avg = 0
#     while True:
#         num = yield avg
#         sum += num
#         count += 1
#         avg = sum / count
#
# avg_g = average()
# avg_g = average()
# print(next(avg_g)) # 在裝飾器中使用了next方法
# print(avg_g.send(10)) # 返回10
# print(avg_g.send(20)) # 返回15
# 在這裏就少了上面一步先調用__next__的步驟
#------------------------------------------------------------------------------------------------------------------------

# def generator():
#     a = [1,2,3]
#     b = ('a','b','c')
#     c = {'A':'a','B':'b'}
#     yield from a # 將a容器中的元素一個一個返回
#     yield from b # 將b容器中的元素一個一個返回
#     yield from c # 將字典的鍵返回回去
#
# g = generator()
# for i in g:
    # print(i)
# 注意 yield from 後面只能跟一個變量
#------------------------------------------------------------------------------------------------------------------------
'''
生成器的表達式
    生成器的表達式與列表推導式是類似的,只是括號不一樣而已,生成器表達式最終拿到的是生成器
'''
# a = [i*2 for i in range(10)] # 這就是列表推導式
# print(a)
#
# g = (i*2 for i in range(10)) # 這就是生成器表達式
# print(g)
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章