生成器

# 生成器函數
# 只要含有 yield 關鍵字的函數都是生成器函數
# yield 不能和 return 共用且須要寫在函數內
# 生成器函數:執行以後會獲得一個生成器做爲返回值
# 生成器既含有 __next__ 方法,也含有 __iter__ 方法,因此生成器也是一個迭代器,能夠使用 __next__ 方法獲取下一個值,也能夠經過 for 循環取值
# yield和return同樣,均可以返回一個值,可是 return 在返回值以後就直接結束一個函數,而 yield 不會
def generator():
    '''含有yield,它是一個生成器函數'''
    print(1)
    yield 'a'


ret = generator()
print(ret)
print(ret.__next__())
'''
<generator object generator at 0x02FCF8D0>
1
a
'''

# 若是我想生成2000000個哇哈哈,用生成器,每生成一個,就返回一個,這樣就不會出現內存不足的問題
def wahaha():
    for i in range(2000000):
        yield '哇哈哈%s' % i


g = wahaha()
for i in g:
    print(i)
 

# send 獲取下一個值的效果和 next 基本一致

# 只是在獲取下一個值的時候,給上一個 yield 的位置傳遞一個數據
# 使用 send 的注意事項
# 第一次使用生成器的時候 是用 next 獲取下一個值
# 最後一個 yield 不能接受外部的值
 
def generator():
    print(123)
    content = yield 1
    print('=======', content)
    print(456)
    arg = yield 2


g = generator()
ret = g.__next__()
print('***', ret)
ret = g.send('hello')   # send的效果和next同樣
print('***', ret)
'''
123
*** 1
======= hello
456
*** 2
'''
 
# 獲取移動平均值
# 10 20 30 10
# 10 15 20 17.5
# avg = sum/count
def average():
    sum = 0
    count = 0
    avg = 0
    while True:
        num = yield avg
        sum += num    # 10
        count += 1    # 1
        avg = sum/count


avg_g = average()
avg_g.__next__()
avg1 = avg_g.send(10)
avg1 = avg_g.send(20)
avg1 = avg_g.send(30)
print(avg1)

 

# 預激生成器的裝飾器
 
def init(func):   # 裝飾器
    def inner(*args,**kwargs):
        g = func(*args,**kwargs)    # g = average()
        g.__next__()
        return g
    return inner


@init
def average():
    sum = 0
    count = 0
    avg = 0
    while True:
        num = yield avg
        sum += num    # 10
        count += 1    # 1
        avg = sum/count


avg_g = average()   # ===> inner
ret = avg_g.send(10)
print(ret)
ret = avg_g.send(20)
print(ret)
 

# python 3 新特性
 
# python 2
# def generator():
#     a = 'abcde'
#     b = '12345'
#     for i in a:
#         yield i
#     for i in b:
#         yield i


# python 3
def generator():
    a = 'abcde'
    b = '12345'
    yield from a
    yield from b


g = generator()
for i in g:
    print(i)
'''
a
b
c
d
e
1
2
3
4
5
'''
 

 

# 生成器表達式python

# 列表推導式
print([i*i for i in range(10)])
# 生成器表達式
print(i for i in range(10))
'''
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
<generator object <genexpr> at 0x0120FAB0>
'''

 

 # 生成器面試題面試

 # 面試題1函數

def demo():
    for i in range(4):
        yield i


# 生成器都是惰性執行的,只有要它執行的時候它纔會去執行
g = demo()  # 生成器對象

g1 = (i for i in g)
g2 = (i for i in g1)

print(list(g1))  # list(g1)把g1當中全部的內容取出來
print(list(g2))  # g1執行完以後已經空了,因此list(g2)爲空列表
'''
[0, 1, 2, 3]
[]
'''

# 面試題2spa

def add(n, i):
    return n+i


def test():
    for i in range(4):
        yield i


g = test()
for n in [1, 10]:
    g = (add(n, i) for i in g)  # 從上到下,一直到這裏,生成器都沒有取過值
'''至關於
n = 1
g = (add(n, i) for i in g)

n = 10
g = (add(n, i) for i in (add(n, i) for i in test()))
這裏,n = 10,而不是 n = 1,既
g = (add(10, i) for i in (add(10, i) for i in [0, 1, 2, 3]))
因此,最後結果爲 [20, 21, 22, 23]
'''

print(list(g))  # 在這裏,生成器纔開始取值
# [20, 21, 22, 23]
相關文章
相關標籤/搜索