生成器

生成器函數

一個包含yield關鍵字的函數就是一個生成器函數。yield能夠爲咱們從函數中返回值,可是yield又不一樣於return,return的執行意味着程序的結束,調用生成器函數不會獲得返回的具體的值,而是獲得一個可迭代的對象。每一次獲取這個可迭代對象的值,就能推進函數的執行,獲取新的返回值。直到函數執行結束。編程

import time
def genrator_fun1():
    a = 1
    print('如今定義了a變量')
    yield a
    b = 2
    print('如今又定義了b變量')
    yield b

g1 = genrator_fun1()
print('g1 : ',g1)       #打印g1能夠發現g1就是一個生成器
print('-'*20)   #我是華麗的分割線
print(next(g1))
time.sleep(1)   #sleep一秒看清執行過程
print(next(g1))

初識生成器函數

從這能夠說明生成器能夠節省內存函數

#初識生成器二

def produce():
    """生產衣服"""
    for i in range(2000000):
        yield "生產了第%s件衣服"%i

product_g = produce()
print(product_g.__next__()) #要一件衣服
print(product_g.__next__()) #再要一件衣服
print(product_g.__next__()) #再要一件衣服
num = 0
for i in product_g:         #要一批衣服,好比5件
    print(i)
    num +=1
    if num == 5:
        break

#到這裏咱們找工廠拿了8件衣服,我一共讓個人生產函數(也就是produce生成器函數)生產2000000件衣服。
#剩下的還有不少衣服,咱們能夠一直拿,也能夠放着等想拿的時候再拿

初識生成器二

生成器的應用

import time


def tail(filename):
    f = open(filename)
    f.seek(0, 2) #從文件末尾算起
    while True:
        line = f.readline()  # 讀取文件中新的文本行
        if not line:
            time.sleep(0.1)
            continue
        yield line

tail_g = tail('tmp')
for line in tail_g:
    print(line)

生成器監聽文件輸入的例子

對於 send的解釋

def generator():
    print(123)
    content = yield 1
    print('=======',content)
    print(456)
    yield2

g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello')   #send的效果和next同樣
print('***',ret)

#send 獲取下一個值的效果和next基本一致
#只是在獲取下一個值的時候,給上一yield的位置傳遞一個數據
#使用send的注意事項
    # 第一次使用生成器的時候 是用next獲取下一個值
    # 最後一個yield不能接受外部的值

計算移動平均值

def averager():
    total = 0.0
    count = 0
    average = None
    while True:
        term = yield average
        total += term
        count += 1
        average = total/count


g_avg = averager()
next(g_avg)
print(g_avg.send(10))
print(g_avg.send(30))
print(g_avg.send(5))

計算移動平均值(1)

計算移動平均值(2)_預激協程的裝飾器

def init(func):  #在調用被裝飾生成器函數的時候首先用next激活生成器
    def inner(*args,**kwargs):
        g = func(*args,**kwargs)
        next(g)
        return g
    return inner

@init
def averager():
    total = 0.0
    count = 0
    average = None
    while True:
        term = yield average
        total += term
        count += 1
        average = total/count


g_avg = averager()
# next(g_avg)   在裝飾器中執行了next方法
print(g_avg.send(10))
print(g_avg.send(30))
print(g_avg.send(5))

計算移動平均值(2)_預激協程的裝飾器

yield from

def gen1():
    for c in 'AB':
        yield c
    for i in range(3):
        yield i

print(list(gen1()))

def gen2():
    yield from 'AB'
    yield from range(3)

print(list(gen2()))

yield from

列表推倒式和生成器表達式

總結:spa

1.把列表解析的[]換成()獲得的就是生成器表達式code

2.列表解析與生成器表達式都是一種便利的編程方式,只不過生成器表達式更節省內存協程

3.Python不但使用迭代器協議,讓for循環變得更加通用。大部份內置函數,也是使用迭代器協議訪問對象的。例如, sum函數是Python的內置函數,該函數使用迭代器協議訪問對象,而生成器實現了迭代器協議,因此,咱們能夠直接這樣計算一系列值的和:對象

sum(x ** 2 for x in range(4))

而不用這樣例子:blog

sum([x ** 2 for x in range(4)])

 

 

列表推導式

例一:30之內全部與能被3整除的數ip

multiples = [i for i in range(30) if i % 3 is 0]
print(multiples)
# Output: [0, 3, 6, 9, 12, 15, 18, 21, 24, 27]

例二:30之內全部能被3整除的數的平方內存

def squared(x):
    return x*x
multiples = [squared(i) for i in range(30) if i % 3 is 0]
print(multiples)

例三:找到嵌套列表中名字含有兩個‘e’的全部名字get

names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]

print([name for lst in names for name in lst if name.count('e') >= 2])  # 注意遍歷順序,這是實現的關鍵

字典推到式

例一:將一個字典的key和value對調

mcase = {'a': 10, 'b': 34}
mcase_frequency = {mcase[k]: k for k in mcase}
print(mcase_frequency)

例二:合併大小寫對應的value值,將k統一成小寫

mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys()}
print(mcase_frequency)

集合推導式

squared = {x**2 for x in [1, -1, 2]}
print(squared)
# Output: set([1, 4])
相關文章
相關標籤/搜索