精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Python 進階之源碼分析:如何將一個類方法變為多個方法?

開發 后端
前一篇文章《Python 中如何實現參數化測試?》中,我提到了在 Python 中實現參數化測試的幾個庫,并留下一個問題:

 [[286299]]

前一篇文章《Python 中如何實現參數化測試?》中,我提到了在 Python 中實現參數化測試的幾個庫,并留下一個問題:

它們是如何做到把一個方法變成多個方法,并且將每個方法與相應的參數綁定起來的呢?

我們再提煉一下,原問題等于是:在一個類中,如何使用裝飾器把一個類方法變成多個類方法(或者產生類似的效果)?

 

  1. # 帶有一個方法的測試類 
  2. class TestClass: 
  3.     def test_func(self): 
  4.         pass 
  5.  
  6. # 使用裝飾器,生成多個類方法 
  7. class TestClass: 
  8.     def test_func1(self): 
  9.         pass 
  10.     def test_func2(self): 
  11.         pass 
  12.     def test_func3(self): 
  13.         pass 

Python 中裝飾器的本質就是移花接木,用一個新的方法來替代被裝飾的方法。在實現參數化的過程中,我們介紹過的幾個庫到底用了什么手段/秘密武器呢?

1、ddt 如何實現參數化?

先回顧一下上篇文章中 ddt 庫的寫法:

 

  1. import unittest 
  2. from ddt import ddt,data,unpack 
  3. @ddt 
  4. class MyTest(unittest.TestCase): 
  5.     @data((3, 1), (-1, 0), (1.2, 1.0)) 
  6.     @unpack 
  7.     def test(self, firstsecond): 
  8.         pass 

ddt 可提供 4 個裝飾器:1 個加在類上的 @ddt,還有 3 個加在類方法上的 @data、@unpack 和 @file_data(前文未提及)。

先看看加在類方法上的三個裝飾器的作用:

 

  1. # ddt 版本(win):1.2.1 
  2. def data(*values): 
  3.     global index_len 
  4.     index_len = len(str(len(values))) 
  5.     return idata(values
  6.  
  7. def idata(iterable): 
  8.     def wrapper(func): 
  9.         setattr(func, DATA_ATTR, iterable) 
  10.         return func 
  11.     return wrapper 
  12.  
  13. def unpack(func): 
  14.     setattr(func, UNPACK_ATTR, True
  15.     return func 
  16.  
  17. def file_data(value): 
  18.     def wrapper(func): 
  19.         setattr(func, FILE_ATTR, value) 
  20.         return func 
  21.     return wrapper 

它們的共同作用是在類方法上 setattr() 添加屬性。至于這些屬性在什么時候使用?下面看看加在類上的 @ddt 裝飾器源碼:

 

 

 

 

第一層 for 循環遍歷了所有的類方法,然后是 if/elif 兩條分支,分別對應 DATA_ATTR/FILE_ATTR,即對應參數的兩種來源:數據(@data)和文件(@file_data)。

elif 分支有解析文件的邏輯,之后跟處理數據相似,所以我們把它略過,主要看前面的 if 分支。這部分的邏輯很清晰,主要完成的任務如下:

  • 遍歷類方法的參數鍵值對
  • 根據原方法及參數對,創建新的方法名
  • 獲取原方法的文檔字符串
  • 對元組和列表類型的參數作解包
  • 在測試類上添加新的測試方法,并綁定參數與文檔字符串

 

 

 

 

分析源碼,可以看出,@data、@unpack 和 @file_data 這三個裝飾器主要是設置屬性并傳參,而 @ddt 裝飾器才是核心的處理邏輯。

這種將裝飾器分散(分別加在類與類方法上),再組合使用的方案,很不優雅。為什么就不能統一起來使用呢?后面我們會分析它的難言之隱,先按下不表,看看其它的實現方案是怎樣的?

2、parameterized 如何實現參數化?

先回顧一下上篇文章中 parameterized 庫的寫法:

 

  1. import unittest 
  2. from parameterized import parameterized 
  3. class MyTest(unittest.TestCase): 
  4.     @parameterized.expand([(3,1), (-1,0), (1.5,1.0)]) 
  5.     def test_values(self, firstsecond): 
  6.         self.assertTrue(first > second

它提供了一個裝飾器類 @parameterized,源碼如下(版本 0.7.1),主要做了一些初始的校驗和參數解析,并非我們關注的重點,略過。

 

 

 

 

我們主要關注這個裝飾器類的 expand() 方法,它的文檔注釋中寫到:

A "brute force" method of parameterizing test cases. Creates new test cases and injects them into the namespace that the wrapped function is being defined in. Useful for parameterizing tests in subclasses of 'UnitTest', where Nose test generators don't work.

關鍵的兩個動作是:“creates new test cases(創建新的測試單元)”和“inject them into the namespace…(注入到原方法的命名空間)”。

關于第一點,它跟 ddt 是相似的,只是一些命名風格上的差異,以及參數的解析及綁定不同,不值得太關注。

 

 

 

 

最不同的則是,怎么令新的測試方法生效?

parameterized 使用的是一種“注入”的方式:

 

 

 

 

inspect 是個功能強大的標準庫,在此用于獲取程序調用棧的信息。前三句代碼的目的是取出 f_locals,它的含義是“local namespace seen by this frame”,此處 f_locals 指的就是類的局部命名空間。

說到局部命名空間,你可能會想到 locals(),但是,我們之前有文章提到過“locals() 與 globals() 的讀寫問題”,locals() 是可讀不可寫的,所以這段代碼才用了 f_locals。

3、pytest 如何實現參數化?

按慣例先看看上篇文章中的寫法:

 

  1. import pytest 
  2. @pytest.mark.parametrize("first,second", [(3,1), (-1,0), (1.5,1.0)]) 
  3. def test_values(firstsecond): 
  4.     assert(first > second

首先看到“mark”,pytest 里內置了一些標簽,例如 parametrize、timeout、skipif、xfail、tryfirst、trylast 等,還支持用戶自定義的標簽,可以設置執行條件、分組篩選執行,以及修改原測試行為等等。

用法也是非常簡單的,然而,其源碼可復雜多了。我們這里只關注 parametrize,先看看核心的一段代碼:

 

 

 

 

根據傳入的參數對,它復制了原測試方法的調用信息,存入待調用的列表里。跟前面分析的兩個庫不同,它并沒有在此創建新的測試方法,而是復用了已有的方法。在 parametrize() 所屬的 Metafunc 類往上查找,可以追蹤到 _calls 列表的使用位置:

 

 

 

 

最終是在 Function 類中執行:

 

 

 

 

好玩的是,在這里我們可以看到幾行神注釋……

 

 

 

 

閱讀(粗淺涉獵) pytest 的源碼,真的是自討苦吃……不過,依稀大致可以看出,它在實現參數化時,使用的是生成器的方案,遍歷一個參數則調用一次測試方法,而前面的 ddt 和 parameterized 則是一次性把所有參數解析完,生成 n 個新的測試方法,再交給測試框架去調度。

對比一下,前兩個庫的思路很清晰,而且由于其設計單純是為了實現參數化,不像 pytest 有什么標記和過多的抽象設計,所以更易讀易懂。前兩個庫發揮了 Python 的動態特性,設置類屬性或者注入局部命名空間,而 pytest 倒像是從什么靜態語言中借鑒的思路,略顯笨拙。

4、最后小結

回到標題中的問題“如何將一個方法變為多個方法?”除了在參數化測試中,不知還有哪些場景會有此訴求?

本文分析了三個測試庫的裝飾器實現思路,通過閱讀源碼,我們可以發現它們各有千秋,這個發現本身還挺有意思。在使用裝飾器時,表面看它們差異不大,但是真功夫的細節都隱藏在底下。

源碼分析的意義在于探究其所以然,在這次探究之旅中,讀者們可有什么收獲啊?一起來聊聊吧!

責任編輯:華軒 來源: Python貓
相關推薦

2019-12-27 15:05:51

Python類方法裝飾器

2021-05-17 09:50:06

Kubebuilde源碼CURD

2016-09-22 15:50:38

JavascriptRedux源碼解析

2022-11-09 11:01:11

Linux命令后臺

2025-08-14 09:10:01

JavaScript前端開發

2021-03-22 10:20:04

Python元類代碼

2018-09-10 15:14:27

前端WebURL

2010-10-15 13:57:55

MySQL源碼安裝

2021-08-25 10:37:47

物聯網人工智能IoT

2017-09-06 11:21:53

2021-09-26 08:35:17

Android控件寬高

2014-07-04 10:12:09

VimIDE

2011-04-11 15:55:03

商業智能數據

2020-09-24 10:03:54

Python開發語言

2012-08-13 10:16:34

IBMdW

2021-04-21 10:01:53

Python類方法靜態方法

2022-07-19 10:53:57

模型算法智能

2022-09-07 10:20:05

Python裝飾類

2015-08-25 09:17:30

2021-09-27 10:07:39

Python 開發編程語言
點贊
收藏

51CTO技術棧公眾號

一区二区三区 欧美| 99一区二区三区| 日韩一区二区三区四区视频| www.久久爱.com| 亚洲国产日韩一级| 欧美一区二区福利| 国产伦精品一区二区三区四区 | 欧美 日韩 国产 成人 在线观看 | 国产在线精品二区| 真实新婚偷拍xxxxx| 在线日韩av| 日韩视频中文字幕| 国产精品无码一区二区三区免费| 中文字幕系列一区| 亚洲成人免费在线| 一区不卡字幕| 色视频在线观看福利| 国产一区二区三区黄视频 | 一级特黄aaa大片在线观看| 久久久9色精品国产一区二区三区| 亚洲大胆人体在线| 天堂在线一区二区三区| 日韩av大片站长工具| 亚洲乱码精品一二三四区日韩在线| 久久精品二区| 性一交一乱一透一a级| 久久久久久穴| 性色av一区二区三区免费| 黄色片网站在线播放| 亚洲精品国产精品粉嫩| 精品欧美乱码久久久久久1区2区| 日韩精品你懂的| 高清在线视频不卡| 樱桃视频在线观看一区| 一区二区三区欧美在线| 狠狠色伊人亚洲综合网站l| gogogo免费视频观看亚洲一| 97人人模人人爽人人少妇| 欧美性受xxx黑人xyx性爽| 亚洲专区一区二区三区| 欧美精品videosex性欧美| 动漫性做爰视频| 欧美gvvideo网站| 亚洲网站在线播放| 国产精品无码久久久久一区二区| 久久精品色播| 亚洲国产精品悠悠久久琪琪| 亚洲成人精品在线播放| 欧美成年网站| 日韩一区二区在线免费观看| 性久久久久久久久久久久久久| 99只有精品| 欧美视频三区在线播放| 中文字幕国内自拍| 青青国产精品| 宅男在线国产精品| 中文字幕一区二区三区四| 亚洲精品伦理| 91精品久久久久久久99蜜桃| 亚洲欧美天堂在线| 国产一区二区| 日韩久久精品一区| 国产精品成人99一区无码 | 欧美资源一区| 第九色区av在线| 中文字幕不卡在线| 在线视频不卡一区二区三区| 欧美a在线看| 亚洲精品欧美专区| 久久成人福利视频| 亚洲欧洲自拍| 欧美午夜理伦三级在线观看| 色播五月综合网| 国产精品久久免费视频| 欧美zozozo| 少妇大叫太粗太大爽一区二区| 九一国产精品| 少妇高潮 亚洲精品| 一级性生活免费视频| 中文字幕免费一区二区| 久久久久久网站| 欧产日产国产69| 久久福利视频一区二区| 国产精品手机视频| 免费在线视频一级不卡| 国产精品久久久久aaaa樱花| 日本高清视频免费在线观看| 国产h片在线观看| 欧美日韩亚洲不卡| 亚洲av无码一区东京热久久| 亚洲精品合集| 美女啪啪无遮挡免费久久网站| 国产精品9191| 毛片不卡一区二区| 国产欧美在线一区二区| 97超碰国产一区二区三区| 一二三区精品福利视频| 老熟妇仑乱视频一区二区| 91成人小视频| 亚洲片国产一区一级在线观看| 久久久久99精品成人| 99精品国产福利在线观看免费 | 久久久亚洲欧洲日产国码αv| 亚洲第一在线综合在线| av资源在线播放| 欧美精品国产精品| 粉嫩av蜜桃av蜜臀av| 色中色综合网| 欧美在线播放视频| 国产jzjzjz丝袜老师水多| 2021国产精品久久精品| 伊人网在线免费| 78精品国产综合久久香蕉| 亚洲精品一区二区精华| 亚洲女人久久久| 久久国产欧美| 国产欧美日本在线| 国产三级在线播放| 欧美亚洲图片小说| 精品国产av色一区二区深夜久久| 99久久夜色精品国产亚洲96| 日韩免费黄色av| 亚洲精品国产精品乱码不卡| 国产精品初高中害羞小美女文| 日本网站免费在线观看| 亚洲三区欧美一区国产二区| 久久九九国产精品怡红院| 国产字幕在线观看| 91在线视频在线| 欧美狂野激情性xxxx在线观| 国产亚洲字幕| 久久精品国产欧美激情| 国产成人a v| 久久综合久久综合久久综合| 男女日批视频在线观看| 97人人澡人人爽91综合色| 精品国产一区av| 一区二区小视频| 国产日韩v精品一区二区| 成人在线免费观看av| 风间由美中文字幕在线看视频国产欧美| 久久av在线看| 国产特级黄色片| 亚洲精品免费一二三区| 国产欧美激情视频| 亚洲精品一区二区妖精| 国产日韩视频在线观看| av网站大全在线观看| 在线中文字幕一区二区| 成年人在线免费看片| 毛片一区二区| 日韩aⅴ视频一区二区三区| 欧美日韩123区| 国产午夜精品视频免费不卡69堂| 亚洲成人第一网站| 久久亚洲综合色| 久久精品午夜福利| 国产成人精品999在线观看| 国产精品国产三级国产aⅴ浪潮| 牛牛热在线视频| 日本精品视频一区二区三区| 国产精品免费无码| 男人的j进女人的j一区| 亚洲最大免费| 欧美日韩午夜电影网| 欧美激情在线观看视频| 全国男人的天堂网| 精品国产福利视频| 欧美做受高潮6| 久久精品二区亚洲w码| 黄色录像特级片| silk一区二区三区精品视频| 45www国产精品网站| 久久国产精品高清一区二区三区| 欧美视频一区二区三区| 尤物在线免费视频| 国产成人一区在线| 人人妻人人添人人爽欧美一区| 国产精品美女久久久久久不卡| 国产精品一区二区性色av| 超碰在线caoporn| 亚洲国产三级网| 欧美成人精品网站| 夜夜嗨av一区二区三区四季av| 欧产日产国产精品98| 男人的天堂久久精品| 日韩精品在线视频免费观看| 自拍偷拍欧美一区| 91精品在线观| 一区二区乱码| 久久久精品在线观看| 日本成人动漫在线观看| 欧美日韩一区国产| 国产稀缺真实呦乱在线| 中文天堂在线一区| 秘密基地免费观看完整版中文| 视频在线观看一区| 天堂а√在线中文在线| 国产一区二区三区网| 99国产盗摄| 欧洲av一区二区| 欧美第一淫aaasss性| 国产原创av在线| 精品国产免费人成电影在线观看四季| 国产男人搡女人免费视频| 亚洲一区二区在线免费观看视频| 亚洲区自拍偷拍| 成人美女在线观看| 亚洲欧美日韩一二三区| 日韩黄色免费电影| 国产青青在线视频| 欧美成人一品| 一区中文字幕在线观看| 九九精品在线| 国产一区二区高清不卡| 亚洲人成777| 国产精品久久久久久久久借妻 | 日韩一区二区三区免费播放| 国产精品一区二区三区精品| 99re8精品视频在线观看| 国产成人精品在线观看| 激情aⅴ欧美一区二区欲海潮| 久久6免费高清热精品| av网站在线免费播放| 亚洲欧美中文字幕在线一区| 日韩一区二区三区在线观看视频| 在线电影一区二区三区| 高潮无码精品色欲av午夜福利| 懂色av一区二区三区| 激情综合网五月婷婷| 一区二区三区视频在线观看| 男人晚上看的视频| 国产精品乱人伦| 九一在线免费观看| 日本一二三四高清不卡| 人人妻人人澡人人爽| 久久久精品国产免大香伊| 97人妻天天摸天天爽天天| aaa亚洲精品| 四季av综合网站| 成人免费视频一区二区| 精品久久久久久无码人妻| 国产激情一区二区三区| 18深夜在线观看免费视频| 国产乱人伦偷精品视频不卡| 一级黄色片在线免费观看| 久久国产精品99精品国产| 一区二区三区免费播放| 另类小说一区二区三区| 成年人三级黄色片| 精品一区二区在线看| 天天干天天色天天干| 国产在线不卡一区| 日本人dh亚洲人ⅹxx| 粉嫩一区二区三区在线看| 午夜免费福利影院| 99re8在线精品视频免费播放| 真人bbbbbbbbb毛片| 国产日韩欧美精品一区| 9.1片黄在线观看| 亚洲三级理论片| 久久久香蕉视频| 精品日本高清在线播放 | 女同一区二区免费aⅴ| 久久久久久国产精品美女| 国产在线美女| 国产精品露脸自拍| 免费一级欧美片在线观看网站| 国产精品视频免费一区| 欧美色图婷婷| 日韩中文字幕一区二区| 亚洲国产精品久久久久蝴蝶传媒| 日韩成人手机在线| 久久国产精品久久久久久电车| 日韩av手机版| 国产成人精品午夜视频免费| 亚洲成人av免费在线观看| 久久精品视频在线看| 永久av免费网站| 亚洲v日本v欧美v久久精品| 欧美a视频在线观看| 91精品国产欧美一区二区成人| 狠狠躁夜夜躁av无码中文幕| 亚洲视频欧美视频| gogo在线高清视频| 欧美一级电影免费在线观看| 日韩亚洲国产免费| 精品日韩欧美| 午夜av一区| 无码人妻丰满熟妇区96| 美日韩一级片在线观看| 亚洲色偷偷色噜噜狠狠99网| 国产亚洲精品bt天堂精选| 中文字幕在线有码| 欧美午夜美女看片| 国产按摩一区二区三区| 亚洲男人天堂古典| a毛片在线播放| 国产精品成久久久久三级| 一区二区三区四区视频免费观看| 欧美日韩精品免费在线观看视频| 99热国内精品| 亚洲色成人一区二区三区小说| 国产精品综合二区| 舐め犯し波多野结衣在线观看| 樱桃国产成人精品视频| 中文字幕乱码中文字幕| 亚洲黄色成人网| 麻豆视频在线| 国产不卡一区二区在线播放| 哺乳一区二区三区中文视频| 亚洲永久一区二区三区在线| 久久亚洲风情| 喷水视频在线观看| 一区二区三区中文字幕| 亚洲一区二区影视| 亚洲日本中文字幕| 国产精品一区二区日韩| 亚洲综合中文字幕在线观看| 菠萝蜜一区二区| 国产成人精品视频免费看| 成人中文字幕电影| 内射一区二区三区| 欧美日本一区二区在线观看| 蜜芽tv福利在线视频| 91大神在线播放精品| 精品麻豆剧传媒av国产九九九| 亚洲mv在线看| 日韩激情一区二区| 亚洲精品色午夜无码专区日韩| 欧美日韩免费网站| 午夜激情小视频| 久久久久久亚洲精品不卡| 免费一级欧美在线大片| 五月天在线免费视频| 久久99国产精品尤物| 欧美成人短视频| 欧美久久高跟鞋激| 波多野结衣一区二区| 国产精品久久久久久久久久久久久 | 色婷婷综合久久久中文字幕| 天天摸天天碰天天爽天天弄| 国内免费久久久久久久久久久 | 日本一区二区不卡高清更新| 亚洲一区二区伦理| 日韩www视频| 精品久久久久久久中文字幕| 性xxxx视频| 欧美壮男野外gaytube| 亚洲精品无吗| 噼里啪啦国语在线观看免费版高清版| 久久久精品综合| 最新国产中文字幕| 日韩在线播放一区| 久久99精品久久久野外观看| 国产一区二区三区在线免费| 成人毛片老司机大片| 欧美日韩乱国产| 亚洲天堂av在线免费| 不卡亚洲精品| 青青草综合视频| a亚洲天堂av| japanese国产在线观看| 日韩视频精品在线| 51精品国产| 任你操这里只有精品| 国产精品福利影院| www.蜜臀av.com| 欧美一性一乱一交一视频| 欧美理论电影大全| 一级日本黄色片| 精品成人av一区| 粉嫩av一区| 国产传媒一区二区三区| 性感少妇一区| 黄色录像一级片| 亚洲国产日韩欧美在线动漫| 日韩成人亚洲| 国风产精品一区二区| 久久综合给合久久狠狠狠97色69| 一级片在线免费播放| 欧美另类高清videos| 免费看成人哺乳视频网站| 久热在线视频观看| 精品久久久久久久久久国产| 在线免费av电影| 国产一区免费在线观看| 久久精品国产免费| 日韩美女黄色片| 日韩在线观看你懂的| 国产精品任我爽爆在线播放| 黄色三级视频在线| 亚洲一区欧美一区| 日本高清中文字幕在线| 国产有色视频色综合| 国产一区二区三区黄视频 | 国产午夜精品理论片| 亚洲欧美成人精品| 综合激情久久| 中文字幕线观看|