一、Iterable(可迭代對象)
1、可迭代對象:能夠進行迭代操作的對象。
- 可以理解為:能夠使用for循環遍歷的都是可迭代對象;**
- 所有的可迭代對象,偶可以用內置函數iter轉換為迭代器**
2、可迭代對象包括:
- 序列類型:元組、列表、字符串、range
- 字典、集合
- 文件對象(open(xxx))
- 實現了迭代協議(iter)方法的對象
class Myclass1:"""實現迭代協議"""def __iter__(self):# return iter([111,22,33])m = Myclass1()
for i in m :print(i)
- 實現了序列語義方法(getitem)的對象
class Myclass2:"""實現序列語義"""value = [11,22,33]def __getitem__(self, item):return self.value[item]m = Myclass2()
for i in m :print(i)
二、Iterator(迭代器)
**1、迭代器:**實現了迭代器協議的對象(__iter__方法和__next__方法)。
- 能夠使用內置函數next進行逐個迭代數據的對象
li = [111,222,333]
itor = iter(li)
print(next(itor))#每次使用next都能迭代出一個數據
print(next(itor))
2、特性:
- 迭代器內的數據只能迭代一次
- 當迭代器內部的數據,迭代完,,迭代器就會進入停止狀態,如果再次通過next進行迭代就會拋出異常(StopIteration)
三、Generator(生成器;常用)
1、生成器:**生成器是迭代器的子類,可以把他當做一種特殊的迭代器,生成器支持支持迭代器所有的操作和特性。
2、生成器定義的方法:
- 生成器表達式
g = (i for i in xxx)
- 生成器函數:函數中使用了關鍵字yield的函數,都稱之為生成器函數;生成器函數調用時不會直接執行,會直接返回一個生成器對象
def test1():print("-------------1--------------")yield 1print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%")yield 2res = test1()
print(res)
這時打印出的test1函數為生成器對象
3、生成器的應用場景:
- 在程序中使用上萬級別低的數據時,使用生成器來保存數據,可以顯著的減少內存開銷
- 生成器內部不直接保存數據,只存儲生成數據低的規則(算法),使用next去獲取才會生成(用的時候才生產)
- 可以使用生成器來實現函數內部的代碼分段執行(pytest中的fixture實現,python3.5以前的攜程實現
4、運行過程
當效用生成器函數時,他會返回一個生成器對象,該對象可以迭代獲取生成器函數中通過yield語句產生的值。每次迭代時,生成器函數會從上一次yield語句的位置繼續執行,直到再次遇到yield語句并產生下一個值,當超過迭代器中的數據全部取完以后,再取數據則會報錯
5、自動化框架中用到的生成器
使用pytest執行
import pytest@pytest.fixture()
def login_fixture():print("=====用例前置腳本=====")token = 'xxxxxxxx'yield tokenprint("=====用例后置腳本=====")def test_demo(login_fixture):print("=====執行測試用例中=====")
上面的是pytest封裝好的夾具功能,下面的代碼是模擬完整的使用夾具的過程
from inspect import signaturedef login_fixture():print("=====用例前置腳本=====")token = 'xxxxxxxx'yield tokenprint("=====用例后置腳本=====")def demo(login_fixture):print("=====執行測試用例中=====")if __name__ == '__main__':#自動化測試框架中夾具是如何運行的"""1、框架初始運行時,會對所有夾具進行收集,2、檢測用例中是否使用到了夾具,若,則去夾具列表中查詢同名的測試夾具3、存在同名測試夾具,,先執行夾具的前置,再執行測試用例,最后執行夾具的后置腳本"""##檢測函數中定義的參數res = signature(demo).parametersprint(res)#OrderedDict([('login_fixture', <Parameter "login_fixture">)])params = list(res.keys())print(params)#['login_fixture']#判斷參數中是否有同名的測試夾具#for key in params:# pass#如果存在對應的測試夾具,先執行夾具的前置腳本f1 = login_fixture()res = next(f1)#再執行測試用例demo(res)#最后執行夾具的后置腳本try:next(f1)except StopIteration:pass
6、生成器的內置方法
- close方法:關閉生成器,關閉后無法再生成數據了
def work():print("-------------1--------------")s1 = yield 1print("-------------2--------------s1=",s1)s2 = yield 2print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%s2=",s2)yield 3res = work()
print(next(res))
res.close()
print(next(res))
- send方法:和內置函數next一樣,用來生成數據;但是send方法可以再生成數據的同時和生成器內部進行數據交換
- 使用send方法之前,必須先通過next去生成至少一次數據(通過next去啟動生成器)
- send方法必須要傳一個參數(值)且只能傳一個
- send方法傳入的值,會傳到生成器內部上一次,掛起的yield處
def work():print("-------------1--------------")s1 = yield 1print("-------------2--------------s1=",s1)s2 = yield 2print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%s2=",s2)yield 3res = work()
print(next(res))
print(res.send('test1'))#執行時先返回已定義的數據
print(res.send('test'))
結果:
- 主動生成器內部拋出異常(了解)
- 當調用 generator.throw(exc_type, exc_value, traceback) 時,會在生成器內部當前暫停的位置引發一個異常。生成器會嘗試捕獲這個異常,并在適當的位置執行相應的異常處理邏輯。如果生成器內部沒有捕獲到這個異常,或者異常處理邏輯中拋出了新的異常,那么這個異常會傳播到生成器的調用處。
- 相當于在生成器內部上一次掛起的位置,執行raise,拋出異常
generator.throw(exc_type, exc_value=None, traceback=None)- exc_type 表示要拋出的異常類型。- exc_value 表示異常的值,默認為 None。- traceback 表示異常的回溯信息,默認為 None。
PS:
回溯(traceback)信息是指當程序出現異常時,系統會生成一份包含異常發生位置及調用棧信息的報告。這份報告就是回溯信息。
回溯信息通常包含以下內容:
- 異常類型(Exception Type):表示引發異常的類型,例如TypeError、ValueError等。
- 異常值(Exception Value):表示異常的具體信息,通常是一個字符串,描述了異常的原因或相關信息。
- 回溯棧(Traceback Stack):表示調用棧信息,即異常發生時代碼的執行路徑,從最內部的函數或方法開始,逐步向外展示調用關系。
回溯信息可以幫助開發者追蹤和定位異常發生的位置,以及異常拋出時的上下文信息。
在generator.throw()方法中,如果提供了回溯信息(traceback參數),那么該信息將包含在生成器捕獲的異常中,使得異常的回溯信息更加完整。如果沒有提供回溯信息,則系統會自動生成默認的回溯信息。