1. 程式人生 > >08-Python基礎之迭代器與生成器

08-Python基礎之迭代器與生成器

迭代器

可迭代協議:只要含有__iter__方法的都是可迭代的,只要是能被for迴圈的資料型別 就一定擁有__iter__方法

迭代器協議 :內部含有__next__和__iter__方法的就是迭代器

迭代器的好處:

   從容器型別中一個一個的取值,會把所有的值都取到

   節省記憶體空間,迭代器並不會在記憶體中再佔用一大塊記憶體,而是隨著迴圈 每次生成一個,每次next每次給我一個

 

注意:

__next__()方法當取完時候會報錯。
print(dir([]))   #告訴我列表擁有的所有方法,其他的只要改想知道的型別就可以了

 

生成器

生成器 ----也是一種迭代器,即含有__next__和__iter__方法

生成器函式

#只要含有yield關鍵字的函式都是生成器函式
# yield不能和return共用且需要寫在函式內
def generator():
    print(1)
    yield 'a'
# #生成器函式 : 執行之後會得到一個生成器作為返回值
ret = generator()    #得到一個記憶體地址
print(ret)          #<generator object generator at 0x000002774525D830>,通過next取值,一個yield返回一個值
print(ret.__next__()) #列印 1 a

 生成器函式進階:

def generator():
    print('123456789*')
    contend = yield 1
    print('==========',contend)
    print('*987654321')
    yield

g = generator()
print(g.__next__())
#send的效果和next一樣,都是往下執行,只是在獲取下一個值的時候,給上一yield的位置傳遞一個數據
#使用send的注意事項
# 第一次使用生成器的時候 是用next獲取下一個值 # 最後一個yield不能接受外部的值 g.send('hello') # print(g.__next__()) 思考:列印的是什麼? # 獲取移動平均值 # 10 20 30 10 # 10 15 20 17.5 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) 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) ''' 重點思考執行過程?然後能寫下來 '''
View Code

 

生成器表示式

'''
把列表解析的[]換成()得到的就是生成器表示式
'''
#列表解析
li = [i*2 for i in range(5)]        #記憶體佔用大,機器容易卡死
print(li)               #li = [0, 2, 4, 6, 8]
print(type(li))         #<class 'list'>
#生成器表示式
li = (i*2 for i in range(5))   #幾乎不佔記憶體
print(li)                #<generator object <genexpr> at 0x000002BC67B8D930>
print(type(li))         #<class 'generator'>

 

各種推導式:

#列表推導式
multiples = [i for i in range(30) if i % 3 is 0]  #30以內所有能被3整除的數

# def squared(x):
#     return x*x
multiples = [i*i for i in range(30) if i % 3 is 0]  #30以內所有能被3整除的數的平方
print(multiples)

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])  # 注意遍歷順序,這是實現的關鍵

#字典推導式

mcase = {'a': 10, 'b': 34}    #將一個字典的key和value對調
mcase_frequency = {mcase[k]: k for k in mcase}
print(mcase_frequency)

#集合推導式
squared = {x**2 for x in [1, -1, 2]}
print(squared)
# Output: set([1, 4])