生成器函數及表達式,列表推導式

生成器

生成器的本質就是迭代器面試

生成器通常由生成器函數或者生成器表達式來建立app

其實就是手寫的迭代器函數

def func():
    print("娃哈哈")
    yield 1 # return和yield均可以返回數據
    print("呵呵呵")


gen = func() # 獲取生成器,不會執行你的函數. 拿到的是一個生成器
print(gen)# >>> <generator object func at 0x0000021441B634F8>
#不會拿到值,拿到的是個內存地址

生成器的特色

和迭代器同樣.取值方式和迭代器同樣(__next__()spa

send(): 給上一個yield傳值).code

def func():
    print("娃哈哈")
    yield 1
    print("呵呵呵")
gen = func() # 不會執行你的函數. 拿到的是生成器
print(gen.__next__()) #執行函數. 執行到下一個yield.
>>> 結果: 
娃哈哈
1

生成器函數

和普通函數沒有區別. 裏面有yield的函數就是生成器函數.blog

生成器函數在執行的時候. 默認不會執行函數體. 返回生成器內存

def func():
    print("娃哈哈")
    yield 1 # return和yield均可以返回數據
    print("呵呵呵")


gen = func() # 不會執行你的函數. 拿到的是生成器
print(gen)
>>>
<generator object func at 0x00000181098B34F8>

 

yield: 至關於return 能夠返回數據. 可是yield不會完全中斷函數. 分段執行函數generator

yield好處

'''
生成器有什麼好處呢?就是不會一會兒在內存中生成太多數據

假如我想讓工廠給學生作校服,生產2000000件衣服,我和工廠一說,工廠應該是先答應下來,而後再去生產,我能夠一件一件的要,也能夠根據學生一批一批的找工廠拿。
而不能是一說要生產2000000件衣服,工廠就先去作生產2000000件衣服,等回來作好了,學生都畢業了。。。
'''
def order():
    lst = []
    for i in range(200000):
        lst.append("衣服"+str(i))
    return lst
g = order()
print(g) # 這個數據太龐大了,一下處理2000000件衣服...
#咱們加了yield就不同了,咱們能夠根據本身的需求要衣服
def order():
    """生產衣服"""
    for i in range(2000000):
        yield "生產了第%s件衣服"%i

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

經過生成器的__next__()分段執行這個函數.it

send() 給上一個yield傳值, 不能再開頭(沒有上一個yield), 最後一個yield也不能夠用send()for循環

#send() 和__next__()是同樣的. 能夠執行到下一個yield, 能夠給上一個yield位置傳值
def func():
    print("我是第一個段")
    a = yield 123
    print(a)
    print("周杰倫是第二段")
    b = yield 456
    print(b) # ??
    print("林俊杰是第三段")
    c = yield 789
    print(c)
    print("王力宏是最後一個段")
    yield 79      # 最後收尾必定是yield
g = func()
print(g.__next__()) 
print(g.__next__())
print(g.__next__())
print(g.__next__())
>>>
我是第一個段
123
None
周杰倫是第二段
456
None
林俊杰是第三段
789
None
王力宏是最後一個段
79
g = func() #獲取生成器
print(g.__next__()) # 沒有上一個yield 因此不能使用send() 開頭必須是__next__()
print(g.send("煎餅果子")) #向第一個yield傳值
print(g.send("韭菜盒子")) #向上一個yield傳值
print(g.send("鍋包肉"))    #向上一個yield傳值 
>>>
我是第一個段
123
煎餅果子
周杰倫是第二段
456
韭菜盒子
林俊杰是第三段
789
鍋包肉
王力宏是最後一個段
79

推導式

用一句話來生成一個列表

列表推導式

[結果 for循環 條件篩選]

#50之內的奇數
lst = [i for i in range(50) if i%2==1]
print(lst)
>>>
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49]

 字典推導式 {k:v for循環 條件篩選}

#key和value顛倒
dic = {"jj": "林俊杰", "jay": "周杰倫", "zs": "趙四", "ln":"劉能"}
d = {v : k for k,v in dic.items()}
print(d)
>>>
{'林俊杰': 'jj', '周杰倫': 'jay', '趙四': 'zs', '劉能': 'ln'}

 集合推導式

{k for循環 條件}

#集合有去重做用
lst = [1, 1, 4, 6,7,4,2,2]
s = { el for el in lst }
print(s)
>>>
{1, 2, 4, 6, 7} 

生成器表達式

元組tuple沒有推導式,生產器表達式

(結果 for循環 條件)

tu = (i for i in range(10)) # 沒有元組推導式.  生成器表達式
print(tu) # 生成器
>>>
<generator object <genexpr> at 0x00000136D23B34F8>
#既然是生成器那咱們就能夠用 __next__來拿值
print(tu.__next__())
print(tu.__next__())
print(tu.__next__())
print(tu.__next__())
print(tu.__next__())
print(tu.__next__())
print(tu.__next__())
>>>
0
1
2
3
4
5
6

特色:

惰性機制

只能向前

節省內存

#值2000塊的面試題!!!
def func():
    print(111)
    yield 222
    yield 333
g = func() # 獲取生成器
g1 = (i for i in g) # 生成器
g2 = (i for i in g1) # 生成器
print(list(g)) #  111 [222,333] 源頭. 從源頭把數據拿走了
# print(list(g1)) # [] 都是要從源頭拿數據的,因此這裏執行的時候. 源頭已經被g取走了,沒有了數據
# print(list(g2)) #  [] 這裏也沒有值了
#求和
def add(a, b):
    return a  + b

# 生成器函數 #  0-3
def test():
    for r_i in range(4):
        yield r_i
升級版!!!
#0,1,2,3 g = test() # 獲取生成器 for n in [2, 10]: g = (add(n, i) for i in g) # 當n = 2時 g不取值,因沒有值,只是單純遍歷一下並無執 #行,這時候 g = (add(n,),for i in g) # 當n = 10時 g = (add(n+i),for i in add(n+i),for i in g) # 因惰性機制,運行到最後 g開始取值,從源頭取值,源頭g = 0,1,2,3 print(list(g)) # 代數,n =10時 g =(add(10+i),for i in add(10+0,1,2,3)) # i = 10,11,12,13 # 20,21,22,23 #list(g) 一次性全拿出來,因此 list(g) 結果 20,21,22,23
相關文章
相關標籤/搜索