生成器和生成器表達式

一 . 生成器python

  生成器就是迭代器app

  生成器的特色和迭代器同樣.函數

    1.省內存spa

    2.惰性機制code

    3.只能向前對象

  在python中有三種方式獲取生成器blog

    1.經過生成器函數內存

    2.經過各類推導式來實現生成器generator

    3.經過數據的轉換也能夠獲取生成器it

  簡單的生成器函數

def func():    
    print("111")    
    yield 222 

ret = func() 
print(ret) 

結果: 
<generator object func at 0x10567ff68>

   yield和return的效果是同樣的.  有什麼區別呢?  yield是分段來執行一個 函數. return呢? 直接中止執行函數. 

def func():    
    print("111")    
    yield 222    
    print("333")    
    yield 444 

gener = func() 
ret = gener.__next__() 
print(ret) 
ret2 = gener.__next__() 
print(ret2) 
ret3 = gener.__next__()  # 最後⼀一個yield執行完畢. 再次__next__()程序報錯, 也就是 說. 和return無關了了. 
print(ret3) 

結果: 111 
Traceback (most recent call last): 
222 
333  
File "/Users/sylar/PycharmProjects/oldboy/iterator.py", line 55, in <module> 
444    
    ret3 = gener.__next__()  # 最後⼀一個yield執行完畢. 再次__next__()程序報錯, 也 就是說. 和return無關了了. StopIteration

  send和__next__()區別:

    1. send和next()都是讓⽣生成器向下走一次

    2. send能夠給上一個yield的位置傳遞值, 不能給後一個yield發送值. 在第一次執行生
  成器代碼的時候不能使用send()

生成器能夠使用for循環來循環獲取內部的元素

def func():    
    print(111)    
    yield 222    
    print(333)    
    yield 444    
    print(555)    
    yield 666 

gen = func() 
for i in gen:    
    print(i) 

結果: 
111 
222 
333 
444 
555 
666

二 . 推導式

  列表推導式:

lst = [i for i in range(1, 15)] 
print(lst)
 

列表推導式的經常使用寫法:     

  [ 結果 for 變量 in 可迭代對象]

 

 生成器表達式和列表推導式的語法基本上是同樣的. 只是把[]替換成() 

gen = (i for i in range(10)) 
print(gen) 

結果: 
<generator object <genexpr> at 0x106768f10> 

生成器表達式也能夠進行篩選: 

# 獲取1-100內能被3整除的數 
gen = (i for i in range(1,100) if i % 3 == 0) 
for num in gen:    
    print(num) 

# 100之內能被3整除的數的平方 
gen = (i * i for i in range(100) if i % 3 == 0) 
for num in gen:    
    print(num) 

# 尋找名字中帶有兩個e的人的名字 
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],          ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']] 

# 不用推導式和表達式 
result = [] 
for first in names:    
    for name in first:        
        if name.count("e") >= 2:            
            result.append(name) 

print(result) 

# 推導式 
gen = (name for first in names for name in first if name.count("e") >= 2) 
for name in gen:    
    print(name)    

生成器表達式和列表推導式的區別: 

  1. 列表推導式比較耗內存. 一次性加載. 生成器表達式幾乎不佔用內存. 使用的時候才分配和使用內存

  2. 獲得的值不同. 列表推導式獲得的是一個列表. 生成器表達式獲取的是一個生成器.

 生成器的惰性機制: 生成器只有在訪問的時候才取值. 說白了. 你找他要他纔給你值. 不找他要. 他是不會執行的. 

def func():    
    print(111)    
    yield 222 

g = func()  # 生成器g 
g1 = (i for i in g) # 生成器g1. 可是g1的數據來源於g 
g2 = (i for i in g1)    # 生成器g2. 來源g1 

print(list(g))  # 獲取g中的數據. 這時func()纔會被執行. 打印111.獲取到222. g完畢. 
print(list(g1))  # 獲取g1中的數據. g1的數據來源是g. 可是g已經取完了. g1也就沒有數據了 
print(list(g2))  # 和g1同理

  深坑==> 生成器. 要值得時候纔拿值. 

字典推導式: 

# 把字典中的key和value互換 
dic = {'a': 1, 'b': '2'} 
new_dic = {dic[key]: key for key in dic} 
print(new_dic) 

# 在如下list中. 從lst1中獲取的數據和lst2中相對應的位置的數據組成一個新字典 
lst1 = ['jay', 'jj', 'sylar'] 
lst2 = ['周杰倫', '林俊傑', '邱彥濤'] 
dic = {lst1[i]: lst2[i] for i in range(len(lst1))} 
print(dic)

 

集合推導式:

lst = [1, -1, 8, -8, 12] 
# 絕對值去重 

s = {abs(i) for i in lst} 
print(s)

  總結: 推導式有, 列表推導式, 字典推導式, 集合推導式, 沒有元組推導式    

      生成器表達式: (結果 for 變量 in 可迭代對象 if 條件篩選)     

   生成器表達式能夠直接獲取到生成器對象. 生成器對象能夠直接進行for循環. 生成器具備惰性機制

def add(a, b):    
    return a + b

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

g = test()  

for n in [2, 10]:    
    g = (add(n, i) for i in g)

print(list(g))

結果:
[20,21,22,23]

   友情提示: 惰性機制, 不到後不會拿值

  這個題要先讀一下. 而後本身分析出結果. 後用機器跑一下. 

相關文章
相關標籤/搜索