1. 程式人生 > >邁向大神day13 脫稿一期 生成器的進階

邁向大神day13 脫稿一期 生成器的進階

g=generator() #呼叫生成器 list(g) 從生成器中取值的集中方法

  1. next
  2. for
  3. 資料型別的強制裝換 全部取完 佔記憶體

回顧:

迭代器和生成器
迭代器:
雙下方法 : 很少直接呼叫的方法。一般情況下,是通過其他語法觸發的
可迭代的 —— 可迭代協議 含有__iter__的方法('__iter__' in dir(資料))
可迭代的一定可以被for迴圈
迭代器協議: 含有__iter__和__next__方法
迭代器一定可迭代,可迭代的通過呼叫iter()方法就能得到一個迭代器
迭代器的特點:
    很方便使用,且只能取所有的資料取一次
    節省記憶體空間

生成器
生成器的本質就是迭代器
生成器的表現形式
    生成器函式
    生成器表示式
生成器函式:
   含有yield關鍵字的函式就是生成器函式
   特點:
       呼叫函式的之後函式不執行,返回一個生成器
       每次呼叫next方法的時候會取到一個值
       直到取完最後一個,在執行next會報錯

寫生成器實現:有一個檔案,從檔案裡分段讀取內容
readline
read(10)
在讀出來的內容前面加上一個'***',再返回給呼叫者
def generator():
    for i in range(20):
        yield '哇哈哈%s'%i
g = generator()  呼叫生成器函式得到一個生成器
print(list(g))
ret = g.__next__()     每一次執行g.__next__就是從生成器中取值,預示著生成器函式中的程式碼繼續執行
print(ret)
num = 0
for i in g:
    num += 1
    if num > 50:
        break
    print(i)

今日 進階版 優化


def gen():
    print(123)
    yield 1
    print(456)
    yield 2
g=gen()
ret=g.__next__()
print("***",ret)
ret=g.__next__()
print("***",ret)
ret=g.__next__()

優化二

def gen():
    print(123)
    yield 1
    print(456)
    yield 2
g=gen()
ret=g.__next__()
print("***",ret)
ret=g.send('hello'
) print("***",ret)

優化3 的作用

def gen():
    print(123)
    con=yield 1
    print("======",con)
    print(456)
    yield 2
g=gen()
ret=g.__next__()
print("***",ret)
ret=g.send('hello')   #返回 傳值
print("***",ret)

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

只是在獲取下一個值的時候 給上一個yield的位置 傳遞一個數據

!!第一次使用生成器的時候,必須使用next 獲取下一個值

!!最後一個yield不能接受 外部的值

解決最後一個yield的方法

def gen():
    print(123)
    con=yield 1
    print("======",con)
    print(456)
    res= yield 2
    yield 
g=gen()
ret=g.__next__()
print("***",ret)
ret=g.send('hello')   #返回 傳值
print("***",ret)

獲取移動中平均值

def avg():   ##只能執行一次
    sum=0   
    count=0 
    avg=0   
    num=yiel
    sum+=num
    count+=1
    av=sum/c
    yield av
av=avg()    
av.__next__(
avg1=av.send
print(avg1) 

嘿嘿::

更改執行多次

def avg():
    sum=0
    count=0
    avg=0
    num=yiel
    sum+=num
    count+=1
    av=sum/c
    yield av
av=avg()
av.__next__(
avg1=av.send
print(avg1)

再次優化

def avg():       
    sum=0        
    count=0      
    avg=0        
    while  True: 
        num=yield
        sum+=num 
        count+=1 
        avg=sum/c
av=avg()         
av.__next__()    
avg1=av.send(10) 
avg1=av.send(10) 
print(avg1)      

生成器 yield from 輸出每個字元

python 2

def gen():             
    a='abcdf'          
    b='123456'         
    for i in a:        
        yield i        
    for i in b:        
        yield i        
b=gen()                
for i in b:            
    print(i)           

python 3的新特性

def gen():         
    a='abcdf'      
    b='123456'      
    yield from a   ##new
    yield from b   
b=gen()            
for i in b:        
    print(i)       

生成器表示式和 列表表示式

#格式 for 迴圈 [ i for i range(11)] print(egg_list) ######x效果一樣的

egg_list=[]   ###
for  i in range(10)
	egg_list.append('雞蛋%s'%i)
print(egg_list)
'______________________________________________________'
egg_list=['雞蛋%s'%i for i in range(10)]  #列表推倒式

生成器表示式

g=(i for i in range(10)) #生成器表示式 print(g) for i in g: print(i) #括號不一樣 返回值不一樣 ===幾乎不佔用記憶體 (生成器表示式的優點)

egg_list=[‘雞蛋%s’%i for i in range(10)] ##三元運算子 簡化版

推倒式: 遍歷和篩選

[滿足條件的元素相關的操作 for 元素 in 可迭代資料型別 if 元素相關的條件] #篩選器

  • 30之內能被三整除的數 res=[for i in range(30) if i%3==0]

  • 找到巢狀列表中名字含有兩個‘e’的所有名字·

names=[[‘tony’,‘sony’],[‘tim’][‘thomas’]] #男女分開

ton=[name for list in names for name in list if name.count(‘e’)==2]

字典推倒式

  • 字典顛倒 mc={‘a’:10, ‘b’:34}#want {10:‘a’,34:‘b’}

mc1={ mc[k]:k for k in mc} print(mc1)

  • 合併大小寫對應的value值 將k 統一成小寫
mc={'A':10,'b':34,'c':54,'a':7}   {'a':17}    
mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase}
print(mcase_frequency)

print(d.get(‘g’,0)) # 字典 get 不到的話返回提攻的預設值0

集合推倒式 自帶去重複的 squ={x**2 for x in [1,-1,2]} print(squ)

惰性運算