python的迭代器和生成器

本文參考 景霄大神的《python核心技術與實戰》python

一 、python中的容器、可迭代對象、迭代器的使用


 容器: python中一切皆對象, 對象的抽象就是類, 而對象的集就是容器,因此列表, 元祖,字典等都是容器,而且全部的容器都是能夠迭代的(iterable)

  迭代器: 迭代器(iterator)提供了next的方法, 調用這個方法會獲得迭代器的下一個對象,直到取完拋出StopIteration錯誤類型,因此能夠經過可迭代對象調取next方法完成遍歷迭代器。

能夠經過isinstance校驗是否爲可迭代對象isinstanstance(obj, lterable)

二 、生成器


 通俗的解釋是懶人的迭代器, 在使用迭代器構成中全部的元素都會直接一次保存在內存中,可是生成器全部的元素經過調取next動態生成, 直觀的感覺就是節省了不少資源

 舉例:生成一億的迭代器[for i in range(10000000000)],可是在實際運用中並不會使用到每一個元素, 這個時候用生成器替代迭代器會更高效,也並不會報OOM異常, 生成器寫法 ( for i in range(100000000))

 做用:迭代器和生成器二者區別還不止內存消耗,迭代器是有窮的,可是由於生成器是動態生成元素,理論上它是能夠無限生成下一個元素的,

實例1 計算 (1 + 2 + 3 + ... + n)

def generator(k):
	i = 1
	while True:
		yield i ** k
		i = i + 1

gen = gennerator(1)
def get_sum(n): 
	sum = 0
	for i in range(n):
		_next = next(gen)
		print(_next)
 
複製代碼
 就跟這個公式同樣, n能夠取無窮, 一樣理論上生成器也能夠取無窮, 上述代碼用yield暫停了函數,而且跳轉到next()函數, i ** k 即爲next返回值, yield的用法還有不少, 能夠代替線程用協程的方法完成函數塊的切換,省去了線程間切換消耗的資源,能夠用send激活, 這邊講了其中一種用法, 一樣它也就是用next激活了生成器。

實例2 在列表中查找某個數字的位置

def func1(list, k):
	out_list = []
	for i, num in enumerate(list):
		if num == k:
			print('fonud it ', i)

def func2(list, k):
	for i, num in enumerate(list):
		if num == k:
			yield i

複製代碼

ps: func2就是生成了一個迭代器對象, 再轉list就能夠了, 可讓代碼更加有可讀性。markdown

實例3 查找列表中是否包含子列表

def is_instance(check_list, list):
	list = iter(list)
	
	return all( i in list for i in check_list) # all()函數必須全部返回均爲True纔會返回True
複製代碼

3、總結

  •  容器是可迭代對象, 可迭代對象調用iter()函數能夠獲得一個迭代器, 迭代器經過next()獲得下一個元素, 從而支持遍歷, 注意點: 迭代器遍歷只可使用一次,緣由是由於迭代器會存到緩衝區內, 經過移動指針來消耗緩衝區, 隨時讀取,可是讀過一次以後指針就在緩衝區的末尾, 因此不可重複讀取。
  •  生成器是一種特殊的迭代器,合理使用生成器能夠下降內存佔用,優化程序結構,提升程序運行速度
  •  生成器也是在python2中協程的一種重要的實現方式(在python中因爲GIL的存在每每使用多進程+協程的方式實現併發), 而在python3.5以上引用了async await語法糖
相關文章
相關標籤/搜索