python全棧闖關--14-生成器進階

一、複習

def generator():
    print('1')
    yield 'a'
    print('2')
    yield 'b'
    print('3')

g = generator()
res = g.__next__()  # 第一個__next__執行到第一個yiled中止, 並返回第一個yiled處的值
print(res)
res = g.__next__()  # 第二個__next__執行到第二個yiled中止, 並返回第二個yiled處的值
print(res)
res = g.__next__()  # 雖然執行了print('3')操做,可是報錯,由於後續沒有yiled了,爲了不報錯,能夠結尾加上yiled
print(res)

二、send

def generator():
    print('1')
    num = yield 'a'  # 此處若是繼續執行,使用__next__觸發,num將會被複制None。使用send,num將會接收seed的值
    print("seed num:%s" % num)
    print('2')
    yield num * 2
    print('3')
    yield

g = generator()
res = g.__next__()  # 第一個__next__執行到第一個yiled中止, 並返回第一個yiled處的值
print(res)
res = g.send(10)  # 發送值給生成器內部,並返回下一個yiled處的值
print(res)
res = g.__next__()  # 雖然執行了print('3')操做,可是報錯,由於後續沒有yiled了,爲了不報錯,能夠結尾加上yiled
print(res)  # 因爲yield沒有返回值,返回None

 

  • send的獲取下一個值得能力和next一致。
  • send時,傳遞值給當前send位置的yield,並執行代碼帶一個yiled處中止
  • 使用send注意事項:
    • 第一次獲取生成器的值時,使用next,不能以開始就是用send
    • 最後一個yiled的位置,不能使用send,不然會報錯「StopIteration」

三、yield from

yiled from 能夠從生成器函數中,依次返回各個值函數

def func():
    s = 'abcd'
    num = '1234'
    yield from s
    yield from num

for i in func():
    print(i)

 

 四、生成器表達式

生成器表達式:在一行代碼中,完成生成器spa

結構: (元素 for 元素 in 元素範圍)code

生成器表達式:blog

g = (i for i in range(10))

for i in g:
    print(i)

不調用不返回值,幾乎不暫用內存內存

若是把括號改爲方括號,則是列表推導式utf-8

g = [i for i in range(10)]
print(g)  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

區別是列表推導式執行完畢時,列表就生成了,已經分配內存get

 

五、各類推導式

列表推導式generator

[每個元素或者和元素相關的操做 for 元素 in 可迭代數據類型]   #遍歷以後挨個處理it

[知足條件的元素相關操做 for 元素 in 可迭代數據類型 if 元素相關的操做]  #篩選io

# 30之內全部能被3整除的數
ret = [i for i in range(30) if i%3 == 0]
print(ret)

# 30之內全部能被3整除的數的平方
ret = [i*i for i in range(30) if i%3 == 0]
print(ret)

# 找到嵌套列表中名字含有兩個‘e’的全部名字

names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
ret = [name for lst in names for name in lst if name.count('e') == 2]
print(ret)

 

字典推導式:

# 例一:將一個字典的key和value對調
mcase = {'a': 10, 'b': 34}
dic = { mcase[k]:k for k in mcase}
print(dic)

# 例二:合併大小寫對應的value值,將k統一成小寫
mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
dic = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase}
print(dic)

 

集合推導式:

#集合推導式,自帶結果去重功能
squared = {i*i for i in [1, -1, 2]}
print(squared)

 

六、練習

# 獲取移動平均值
def move_arg():
    sum = 0
    count =0
    avg = 0
    while 1:
        num = yield avg
        sum += num
        count += 1
        avg = sum / count

g = move_arg()
print(g.__next__())
print(g.send(10))
print(g.send(20))
print(g.send(30))
print(g.send(10))

使用裝飾器,完善上述代碼,是代碼,使代碼運行更加順暢

def init(f):
    def warp():
        g = f()  # 調用生成器函數,獲得一個生成器
        g.__next__()  # 預激活,執行next
        return g  # 返回激活器
    return warp

@init
def move_arg():
    sum = 0
    count =0
    avg = 0
    while 1:
        num = yield avg
        sum += num
        count += 1
        avg = sum / count


g = move_arg()

 

# 3.處理文件,用戶指定要查找的文件和內容,將文件中包含要查找內容的每一行都輸出到屏幕
def check_file(file,find_str):
    with open(file,encoding ='utf-8') as f :
        for i in f:
            if find_str in i:
                yield i

g = check_file("總結複習.py",'迭代器')
for i in g:
    print(i, end='')
# 4.寫生成器,從文件中讀取內容,在每一次讀取到的內容以前加上‘***’以後再返回給用戶。
def get_line(file):
    with open(file,encoding ='utf-8') as f:
        for i in f:
            yield "***" + i


g = get_line("總結複習.py")
for i in g:
    print(i, end='')

 

七、總結和複習

  • 迭代器和生成器
  • 迭代器
    • 可迭代協議: 含有__iter__方法的都是可迭代的
    • 迭代器協議:含有__next__和__iter__方法的都是迭代器
    • 特色:
      • 節省內存
      • 能夠方便的遍歷去到每個值
  • 生成器——本質是一個迭代器
    • 生成器函數:
    • 含有yield關鍵字的都是迭代器
    • 生成器的特色:
      • 調用函數以後函數內的代碼不會執行,返回生成器
      • 每次從生成器中取一個值,都會執行一段代碼,到yiled就中止
    • 如何從生成器中取值:
      • for:若是沒有break會一直取完
      • next:一次只取一個值
      • send:不能用在第一個和最後一個,取下一個值得時候,給上一個值得位置,傳遞一個新的值
      • 數據類型強制轉換:會一次性獲得全部的值,暫用內存
    • 生成器表達式:
      • (符合條件的元素i for i in 可迭代 if 條件)
相關文章
相關標籤/搜索