最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

分析在Python中何種情況下需要使用斷言

 更新時間:2015年04月01日 11:57:25   投稿:goldensun  
這篇文章主要介紹了分析在Python中何種情況下需要使用斷言,以避免在斷言使用中經(jīng)??赡芘龅降腻e誤,作者給出了具體代碼示例,需要的朋友可以參考下

這個問題是如何在一些場景下使用斷言表達式,通常會有人誤用它,所以我決定寫一篇文章來說明何時使用斷言,什么時候不用。

為那些還不清楚它的人,Python的assert是用來檢查一個條件,如果它為真,就不做任何事。如果它為假,則會拋出AssertError并且包含錯誤信息。例如:
 

py> x = 23
py> assert x > 0, "x is not zero or negative"
py> assert x%2 == 0, "x is not an even number"
Traceback (most recent call last):
File "", line 1, in
AssertionError: x is not an even number

很多人用assert作為一個很快和容易的方法來在參數(shù)錯誤的時候拋出異常。但這樣做是錯的,非常錯誤,有兩個原因。首先AssertError不是在測試參數(shù)時應(yīng)該拋出的錯誤。你不應(yīng)該像這樣寫代碼:
 

if not isinstance(x, int):
raise AssertionError("not an int")

你應(yīng)該拋出TypeError的錯誤,assert會拋出錯誤的異常。

但是,更危險的是,有一個關(guān)于assert的困擾:它可以被編譯好然后從來不執(zhí)行,如果你用 –O 或 –oo 選項運行Python,結(jié)果不保證assert表達式會運行到。當適當?shù)氖褂胊ssert時,這是未來,但是當assert不恰當?shù)氖褂脮r,它會讓代碼用-O執(zhí)行時出錯。

那什么時候應(yīng)該使用assert?沒有特定的規(guī)則,斷言應(yīng)該用于:

  •     防御型的編程
  •     運行時檢查程序邏輯
  •     檢查約定
  •     程序常量
  •     檢查文檔

(在測試代碼的時候使用斷言也是可接受的,是一種很方便的單元測試方法,你接受這些測試在用-O標志運行時不會做任何事。我有時在代碼里使用assert False來標記沒有寫完的代碼分支,我希望這些代碼運行失敗。盡管拋出NotImplementedError可能會更好。)

關(guān)于斷言的意見有很多,因為它能確保代碼的正確性。如果你確定代碼是正確的,那么就沒有用斷言的必要了,因為他們從來不會運行失敗,你可以直接移除這些斷言。如果你確定檢查會失敗,那么如果你不用斷言,代碼就會通過編譯并忽略你的檢查。

在以上兩種情況下會很有意思,當你比較肯定代碼但是不是絕對肯定時??赡苣銜e過一些非常古怪的情況。在這個情況下,額外的運行時檢查能幫你確保任何錯誤都會盡早地被捕捉到。

另一個好的使用斷言的方式是檢查程序的不變量。一個不變量是一些你需要依賴它為真的情況,除非一個bug導(dǎo)致它為假。如果有bug,最好能夠盡早發(fā)現(xiàn),所以我們?yōu)樗M行一個測試,但是又不想減慢代碼運行速度。所以就用斷言,因為它能在開發(fā)時打開,在產(chǎn)品階段關(guān)閉。

一個非變量的例子可能是,如果你的函數(shù)希望在它開始時有數(shù)據(jù)庫的連接,并且承諾在它返回的時候仍然保持連接,這就是函數(shù)的不變量:
 

def some_function(arg):
  assert not DB.closed()
  ... # code goes here
  assert not DB.closed()
  return result

斷言本身就是很好的注釋,勝過你直接寫注釋:

# when we reach here, we know that n > 2

你可以通過添加斷言來確保它:

assert n > 2

斷言也是一種防御型編程。你不是讓你的代碼防御現(xiàn)在的錯誤,而是防止在代碼修改后引發(fā)的錯誤。理想情況下,單元測試可以完成這樣的工作,可是需要面對的現(xiàn)實是,它們通常是沒有完成的。人們可能在提交代碼前會忘了運行測試代碼。有一個內(nèi)部檢查是另一個阻擋錯誤的防線,尤其是那些不明顯的錯誤,卻導(dǎo)致了代碼出問題并且返回錯誤的結(jié)果。

加入你有一些if…elif 的語句塊,你知道在這之前一些需要有一些值:
 

# target is expected to be one of x, y, or z, and nothing else.
if target == x:
  run_x_code()
elif target == y:
  run_y_code()
else:
  run_z_code()

假設(shè)代碼現(xiàn)在是完全正確的。但它會一直是正確的嗎?依賴的修改,代碼的修改。如果依賴修改成 target = w 會發(fā)生什么,會關(guān)系到run_w_code函數(shù)嗎?如果我們改變了代碼,但沒有修改這里的代碼,可能會導(dǎo)致錯誤的調(diào)用 run_z_code 函數(shù)并引發(fā)錯誤。用防御型的方法來寫代碼會很好,它能讓代碼運行正確,或者立馬執(zhí)行錯誤,即使你在未來對它進行了修改。

在代碼開頭的注釋很好的一步,但是人們經(jīng)常懶得讀或者更新注釋。一旦發(fā)生這種情況,注釋會變得沒用。但有了斷言,我可以同時對代碼塊的假設(shè)書寫文檔,并且在它們違反的時候觸發(fā)一個干凈的錯誤
 

assert target in (x, y, z)
if target == x:
  run_x_code()
elif target == y:
  run_y_code()
else:
  assert target == z
  run_z_code()

這樣,斷言是一種防御型編程,同時也是一種文檔。我想到一個更好的方案:
 

if target == x:
  run_x_code()
elif target == y:
  run_y_code()
elif target == z:
  run_z_code()
else:
  # This can never happen. But just in case it does...
  raise RuntimeError("an unexpected error occurred")

按約定進行設(shè)計是斷言的另一個好的用途。我們想象函數(shù)與調(diào)用者之間有個約定,比如下面的:

“如果你傳給我一個非空字符串,我保證傳會字符串的第一個字母并將其大寫?!?/p>

如果約定被函數(shù)或調(diào)用這破壞,代碼就會出問題。我們說函數(shù)有一些前置條件和后置條件,所以函數(shù)就會這么寫:
 

def first_upper(astring):
  assert isinstance(astring, str) and len(astring) > 0
  result = astring[0].upper()
  assert isinstance(result, str) and len(result) == 1
  assert result == result.upper()
  return result

按約定設(shè)計的目標是為了正確的編程,前置條件和后置條件是需要保持的。這是斷言的典型應(yīng)用場景,因為一旦我們發(fā)布了沒有問題的代碼到產(chǎn)品中,程序會是正確的,并且我們能安全的移除檢查。

下面是我建議的不要用斷言的場景:

  •     不要用它測試用戶提供的數(shù)據(jù)
  •     不要用斷言來檢查你覺得在你的程序的常規(guī)使用時會出錯的地方。斷言是用來檢查非常罕見的問題。你的用戶不應(yīng)該看到任何斷言錯誤,如果他們看到了,這是一個bug,修復(fù)它。
  •     有的情況下,不用斷言是因為它比精確的檢查要短,它不應(yīng)該是懶碼農(nóng)的偷懶方式。
  •     不要用它來檢查對公共庫的輸入?yún)?shù),因為它不能控制調(diào)用者,所以不能保證調(diào)用者會不會打破雙方的約定。
  •     不要為你覺得可以恢復(fù)的錯誤用斷言。換句話說,不用改在產(chǎn)品代碼里捕捉到斷言錯誤。
  •     不要用太多斷言以至于讓代碼很晦澀。

相關(guān)文章

  • 在python中實現(xiàn)導(dǎo)入一個需要傳參的模塊

    在python中實現(xiàn)導(dǎo)入一個需要傳參的模塊

    這篇文章主要介紹了在python中實現(xiàn)導(dǎo)入一個需要傳參的模塊,具有很好的參考價值,希望可以給大家一個參考,以后在遇到這種的情況的時候,知道如何應(yīng)對
    2021-05-05
  • 詳解Python+OpenCV進行基礎(chǔ)的圖像操作

    詳解Python+OpenCV進行基礎(chǔ)的圖像操作

    OpenCV是一個用于計算機視覺和圖像操作的免費開源庫,有數(shù)千種優(yōu)化的算法和函數(shù)用于各種圖像操作。本文將使用OpenCV在Python中進行一些圖像操作,感興趣的可以學習一下
    2022-02-02
  • Python函數(shù)參數(shù)和注解的使用

    Python函數(shù)參數(shù)和注解的使用

    本文介紹了Python函數(shù)的四種參數(shù):定位參數(shù)、可變參數(shù)、默認值參數(shù)、關(guān)鍵字參數(shù),和第五種Python3新特性參數(shù):僅限關(guān)鍵字參數(shù)。函數(shù)注解是一種元數(shù)據(jù),存在__annotations__屬性中,備注函數(shù)的參數(shù)和返回值的類型,它只是個注解,Python不會做任何強制檢查。
    2021-06-06
  • Django配置跨域并開發(fā)測試接口

    Django配置跨域并開發(fā)測試接口

    這篇文章主要介紹了Django配置跨域并開發(fā)測試接口,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-11-11
  • Python棧算法的實現(xiàn)與簡單應(yīng)用示例

    Python棧算法的實現(xiàn)與簡單應(yīng)用示例

    這篇文章主要介紹了Python棧算法的實現(xiàn)與簡單應(yīng)用,簡單講述了棧的原理并結(jié)合實例形式給出了基于棧實現(xiàn)的進制轉(zhuǎn)換與括號匹配等相關(guān)使用技巧,需要的朋友可以參考下
    2017-11-11
  • python FTP編程基礎(chǔ)入門

    python FTP編程基礎(chǔ)入門

    這篇文章主要介紹了python FTP編程基礎(chǔ)入門的的相關(guān)資料,幫助大家更好的理解和學習使用python,感興趣的朋友可以了解下
    2021-02-02
  • Python使用正則表達式實現(xiàn)爬蟲數(shù)據(jù)抽取

    Python使用正則表達式實現(xiàn)爬蟲數(shù)據(jù)抽取

    這篇文章主要介紹了Python使用正則表達式實現(xiàn)爬蟲數(shù)據(jù)抽取,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08
  • python 實現(xiàn)矩陣填充0的例子

    python 實現(xiàn)矩陣填充0的例子

    今天小編就為大家分享一篇python 實現(xiàn)矩陣填充0的例子,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-11-11
  • python人工智能tensorflow函數(shù)tf.layers.dense使用方法

    python人工智能tensorflow函數(shù)tf.layers.dense使用方法

    這篇文章主要介紹了python人工智能tensorflow函數(shù)tf.layers.dense的使用方法,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05
  • 詳談Python2.6和Python3.0中對除法操作的異同

    詳談Python2.6和Python3.0中對除法操作的異同

    下面小編就為大家?guī)硪黄斦凱ython2.6和Python3.0中對除法操作的異同。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04

最新評論

兰州市| 冷水江市| 遂溪县| 赣榆县| 玉环县| 民县| 怀来县| 时尚| 德惠市| 通海县| 布拖县| 新巴尔虎左旗| 石首市| 汉沽区| 临潭县| 安陆市| 静宁县| 静宁县| 乌鲁木齐市| 石家庄市| 开化县| 扬中市| 堆龙德庆县| 双柏县| 虹口区| 灵寿县| 北宁市| 峡江县| 侯马市| 准格尔旗| 稻城县| 蒙自县| 漠河县| 塔河县| 保康县| 金塔县| 徐州市| 平邑县| 临湘市| 台北县| 含山县|