@TOC
生成器
生成器使用
通過列表?成式,我們可以直接創建?個列表。但是,受到內存限制,列表容量肯定是有限的。?且,創建?個包
含100萬個元素的列表,不僅占?很?的存儲空間,如果我們僅僅需要訪問前??個元素,那后?絕?多數元素占
?的空間都??浪費了。所以,如果列表元素可以按照某種算法推算出來,那我們是否可以在循環的過程中不斷推
算出后續的元素呢?這樣就不必創建完整的list,從?節省?量的空間。在Python中,這種?邊循環?邊計算的機
制,稱為?成器:generator。
創建生成器,列表生成式,我們知道,只要將最外一層的中括號,改為小括號,?成器保存的是算法,每次調? next(g) ,就計算出 g 的下?個元素的值,直到計算到最后?個元素,沒有更多的元素時,拋出 StopIteration 的異常。當然,這種不斷調? next() 實在是太繁瑣了,雖然是點一次出現一次,但正確的?法是使? for 循環,因為?成器也是可迭代對象。所以,我們創建了?個?成器后,基本上永遠不會調?next() ,?是通過 for 循環來迭代它,并且不需要關心StopIteration 異常。
list1 = [x for x in range(1,10)]
print(list1)
# 如何不讓內存溢出 引入生成器(按照一個生成式來創建元素)
g = (x for x in range(1,10))
print(g)
print(next(g))
通過函數來創建生成器(yield)
通過斐波那契數列來實現
普通實現:
def test1(times):#初始化a,b=0,1n=0while n<times:print(b) # yield b #yield用于創建一個生成器,工作返回后面變量值給生成器a,b=b,(a+b)n+=1return "done"print(test1(6))
生成器方式實現:
#引出生成器:對象,保存了產生元素的算法,同時會記錄游標的位置
# 創建一個生成器: 1、通過列表生成式來創建
# 2、通過函數來創建生成器(yield)
# 遍歷生成器中元素內容:
# 1、通過next(g) ,當已經遍歷到生成器的結尾拋異常 :StopIteration
# 2、通過for來遍歷
# 3、object內置的__next__ :當已經遍歷到生成器的結尾拋異常 :StopIteration
# 4、send 函數 ,但是生成器的第一個值必須使用send(None),后面的值就沒有限制(不推薦使用)
def test2():#初始化a,b=0,1while True:temp = yield b #yield用于創建一個生成器,工作返回后面變量值給生成器,無返回值a,b=b,a+bprint(temp)
g4 =test2()
print(g4)
print(next(g4))
print(next(g4))
print(next(g4))print(g4.send(None))
print(g4.send(''))
print(g4.send(''))
print(g4.send(''))
print(g4.send(''))
?成器是這樣?個函數,它記住上?次返回時在函數體中的位置。對?成器函數的第?次(或第 n 次)調?跳轉?
該函數中間,?上次調?的所有局部變量都保持不變。?成器不僅“記住”了它數據狀態;?成器還“記住”了它在流
控制構造(在命令式編程中,這種構造不只是數據值)中的位置。?成器的特點:
- 節約內存
- 迭代到下?次的調?時,所使?的參數都是第?次所保留下的,在整個所有函數調?的參數都是第?次所調?時保
留的,?不是新創建的
迭代器
迭代是訪問集合元素的?種?式。迭代器是?個可以記住遍歷的位置的對象。迭代器對象從集合的第?個元素開始
訪問,直到所有的元素被訪問完結束。迭代器只能往前不會后退。
我們已經知道,可以直接作用于 for 循環的數據類型有以下幾種:
一類是集合數據類型,如 list 、 tuple 、 dict 、 set 、 str 等;
一類是 generator ,包括生成器和帶 yield 的generator function。
這些可以直接作用于 for 循環的對象統稱為可迭代對象: Iterable 。
那我們怎么判斷一組數據或是一組數據對象是不是 Iterable 對象尼?
可以使? isinstance() 判斷?個對象是否是 Iterable 對象
from collections.abc import Iterable
# Iterable:可迭代對象,能夠通過for循環來遍歷
a=(1,)
b=[1,2]
c={}
def test1(args):if isinstance(args,Iterable):print("args是可迭代對象")else:print('args對象不是可迭代對象')
test1(a)
test1(b)
test1(c)
test1(10)
可以被next()函數調?并不斷返回下?個值的對象稱為迭代器
def test2(arg):if isinstance(arg, Iterator):print("args是迭代器")else:print('args對象不是迭代器')
test2(a)
test2(b)
test2(c)
test2(x for x in