【Python內置函數map和zip+上下文管理器及其實現原理】

2022-12-14 14:06:31 來源:51CTO博客

一、map

作用

map: 自動將可迭代對象遍歷,把遍歷出來的數據,當成參數傳入map第一個接口的函數中,將函數執行的結果,放到一個迭代器中進行返回

語法

map(function, iterable, ...)第一個參數 function 以參數序列中的每一個元素調用 function 函數,返回包含每次 function 函數返回值的新列表。iterable -- 一個或多個序列注意:map() 返回的是一個對象。如需展示列表,需手動 list() 轉換。如果要打印返回的列表,需要加上list

res = map(lambda x: x * 2, [1, 2, 3, 4, 5])print(res)print(list(res))#輸出結果[2, 4, 6, 8, 10]
res2 = map(lambda x, y, z: {"sum": x + y}, [1, 2, 3, 4, 5], [11, 22, 33, 44, 55], [111, 222, 333])print(list(res2))#輸出結果[{"sum": 12}, {"sum": 24}, {"sum": 36}]

map與zip組合使用


【資料圖】

title = [    ["id","name","age"],    ["1","XM","18"],    ["2","XH","20"],    ["3","XG","19"],    ["4","GX","14"],]res1 = [i for i in map(lambda x:dict(zip(title[0],x)),title[1:]) if int(i["id"])>2]res2=list(map(lambda x:dict(zip(title[0],x)),title[1:]))print(res1)print(res2)#輸出[{"id": "3", "name": "XG", "age": "19"}, {"id": "4", "name": "GX", "age": "14"}][{"id": "1", "name": "XM", "age": "18"}, {"id": "2", "name": "XH", "age": "20"}, {"id": "3", "name": "XG", "age": "19"}, {"id": "4", "name": "GX", "age": "14"}]

二、zip

作用

zip函數用于將可迭代的對象作為參數,將對象中對應的元素打包成一個個元組,然后返回由這些元組組成的列表(可迭代對象,可以用next取值)。

如果各個迭代器的元素個數不一致,則返回列表長度與最短的對象相同利用 * 號操作符,可以將元組解壓為列表注意:zip() 返回的是一個對象。如需展示列表,需手動 list() 轉換。
li0 = [1, 2, 3, 4]li = [11, 22, 33, 44]li2 = [111, 222, 333, 444, 555, 666]res = zip(li)# 注意點:迭代器對象中的數據,迭代完就沒有了print(next(res))print(list(res))#輸出(11,)[(22,), (33,), (44,)]
li0 = [1, 2, 3, 4]li1 = [11, 22, 33, 44]li2 = [111, 222, 333, 444, 555, 666]res = zip(li1, li2)# 注意點:迭代器對象中的數據,迭代完就沒有了print(list(res))# 三個參數res2 = zip(li0,li1, li2)print(list(res2))#輸出[(11, 111), (22, 222), (33, 333), (44, 444)][(1, 11, 111), (2, 22, 222), (3, 33, 333), (4, 44, 444)]

語法

zip([iterable, ...]) ,iterabl -- 一個或多個迭代器;

nums = ["flower","flow","flight"]print(list(zip(*nums)))#輸出[("f", "f", "f"), ("l", "l", "l"), ("o", "o", "i"), ("w", "w", "g")]

通過zip將兩個列表合成字典

title = ["case_id", "case_title", "url", "data", "expected"]data = [1, "用例1", "www.baudi.com", "001", "ok"]res = zip(title,data)print(list(res))dic = dict(zip(title,data))print(dic)#輸出[("case_id", 1), ("case_title", "用例1"), ("url", "www.baudi.com"), ("data", "001"), ("expected", "ok")]{"case_id": 1, "case_title": "用例1", "url": "www.baudi.com", "data": "001", "expected": "ok"}

應用舉例:將excel讀取出來的簡單數據組裝成接口測試用例所需的數據格式(鍵值對)

cases = [    ["case_id", "case_title", "url", "data", "excepted"],    [1, "用例1", "www.baudi.com", "001", "ok"],    [4, "用例4", "www.baudi.com", "002", "ok"],    [2, "用例2", "www.baudi.com", "002", "ok"],    [3, "用例3", "www.baudi.com", "002", "ok"],    [5, "用例5", "www.baudi.com", "002", "ok"],]title = cases[0]li = []for i in cases[1:]:    li.append(dict(zip(title, i)))print(li)#輸出[{"case_id": 1, "case_title": "用例1", "url": "www.baudi.com", "data": "001", "excepted": "ok"}, {"case_id": 4, "case_title": "用例4", "url": "www.baudi.com", "data": "002", "excepted": "ok"}, {"case_id": 2, "case_title": "用例2", "url": "www.baudi.com", "data": "002", "excepted": "ok"}, {"case_id": 3, "case_title": "用例3", "url": "www.baudi.com", "data": "002", "excepted": "ok"}, {"case_id": 5, "case_title": "用例5", "url": "www.baudi.com", "data": "002", "excepted": "ok"}]

==================================================================================================================================================================

==================================================================================================================================================================

承接上文,我們來講解管理器:

什么是上下文管理器?

我們常見的上下文管理器with open("test.txt", "w") as f:。with 語句是 Pyhton 提供的一種簡化語法,適用于對資源進行訪問的場合,確保不管使用過程中是否發生異常都會執行必要的“清理”操作,釋放資源,with 語句主要是為了簡化代碼操作。

with:文件使用后自動關閉

# 創建一個文件test.txt,若存在則打開,寫入Hello Python# 創建/打開文件f = open("test.txt", "w")f.write("Hello Python")# 關閉這個文件f.close() # 使用withwith open("test.txt", "w") as f:    f.write("Python")

可以發現:通過 with 語句在編寫代碼時,會使代碼變得更加簡潔,不用再去關閉文件。

with的執行過程:

在執行 with 語句時,首先執行 with 后面的 open 代碼

執行完代碼后,會將代碼的結果通過 as 保存到 f 中

然后在下面實現真正要執行的操作

在操作后面,并不需要寫文件的關閉操作,文件會在使用完后自動關閉

上下文管理器實現原理:

with實際上是python中的關鍵字,它可以開啟一個對象的上下文管理器協議,實際上,在文件操作時,并不是不需要寫文件的關閉,而是文件的關閉操作在 with 的上下文管理器中的協議方法里已經寫好了。當文件操作執行完成后, with語句會自動調用上下文管理器里的關閉語句來關閉文件資源。

簡單來說,就是在一個類里,實現了__enter__和__exit__的方法,這個類的實例就是一個上下文管理器.

__enter__: 進入對象的上下文管理器調用的方法,會返回一個值,并賦值給as關鍵詞之后的變量__exit__:退出對象的上下文管理器調用的方法,定義了處理結束后要做的事情,比如文件的關閉,socket的斷開等例如這個示例:
#自定義一個上下文管理器,模擬with文件操作class MyOpen(object):    def __init__(self,path,mode,encoding="utf8"):        # 記錄要操作的文件路徑和模式        self.__path = path        self.__mode = mode        self.__encoding = encoding        # 打開文件        self.__handle = open(self.__path,self.__mode,encoding=self.__encoding)    def __enter__(self):        print("代碼執行到了__enter__......")        # 返回打開的文件對象引用, 用來給  as 后的變量f賦值        return self.__handle     # 退出方法中,用來實現善后處理工作    def __exit__(self, exc_type, exc_val, exc_tb):        print("代碼執行到了__exit__......")              self.__handle.close() # a+ 打開一個文件用于讀寫。如果該文件已存在,文件指針將會放在文件的結尾。文件打開時會是追加模式。如果該文件不存在,創建新文件用于讀寫。with MyOpen("test.txt","a+") as f:    # 創建寫入文件    f.write("Hello Python!!!")    print("文件寫入成功")

我們執行一下,通過日志的打印順序。可以知道其執行過程。

代碼執行到了__enter__......文件寫入成功代碼執行到了__exit__......

上下文管理器的異常處理

異常可以在__exit__ 進行捕獲并由你自己決定如何處理,是拋出還是不拋出。在__exit__ 里返回 True(沒有return 就默認為 return False),就相當于告訴 Python解釋器,這個異常我們已經捕獲了,不需要再往外拋了。

在 寫__exit__ 函數時,需要注意的事,它必須要有這三個參數:

exc_type:異常類型exc_val:異常值exc_tb:異常的錯誤棧信息

當主邏輯代碼沒有報異常時,這三個參數將都為None。

# 編寫兩個數做除法的程序,然后給除數穿入0class MyCount(object):    # 接收兩個參數    def __init__(self,x, y):        self.__x = x        self.__y = y    # 返回一個地址(實質是被as后的變量接收),實例對象就會執行MyCount中的方法:div()    def __enter__(self):        print("代碼執行到了__enter__......")        return self    def __exit__(self, exc_type, exc_val, exc_tb):        print("代碼執行到了__exit__......")        if exc_type == None:            print("程序沒問題")        else:            print("程序有問題,如果你能你看懂,問題如下:")            print("Type: ", exc_type)            print("Value:", exc_val)            print("TreacBack:", exc_tb)         # 返回值決定了捕獲的異常是否繼續向外拋出        # 如果是 False 那么就會繼續向外拋出,程序會看到系統提示的異常信息        # 如果是 True 不會向外拋出,程序看不到系統提示信息,只能看到else中的輸出        return  True     def div(self):        print("代碼執行到了除法div")        return self.__x / self.__y  with MyCount(1, 0) as mc:    mc.div()

輸出如下

標簽: 文件操作 一個對象 自動關閉

上一篇:環球熱門:stm32定時器引腳分布,定時器2~7、9~14基本配置,PWM波電機調速簡單代碼
下一篇:【Python 68個內置函數】