A级片三级毛片中文字幕|97人人干人人爱|aaaaa毛片亚洲av资源网|超碰97在线播放|日本一a级毛片欧美一区黄|日韩专区潮吹亚洲AV无码片|人人香蕉视频免费|中文字幕欧美激情极品|日本高清一级免费不卡|国模大胆在线国产啪视频

AQF
首頁 備考指南 精品課程 名師團隊 職業(yè)前景
您現(xiàn)在的位置:首頁備考必備AQF資料 Python編程中的反模式,AQFer關注下

Python編程中的反模式,AQFer關注下

發(fā)表時間: 2018-10-24 11:04:51 編輯:tansy

這篇文章收集了AQFer在Python編程新手開發(fā)者寫的代碼中所見到的不規(guī)范但偶爾又很微妙的問題。本文的目的是為了幫助那些新手開發(fā)者渡過寫出丑陋的Python代碼的階段。對于那些新手開發(fā)者,總有一些使用反模式的理由,AQFer已經(jīng)嘗試在可能的地方給出了這些理由。但通常這些反模式會造成代碼缺乏可讀性、更容易出bug且不符合Python的代碼風格。

  這篇文章收集了AQFer在Python編程新手開發(fā)者寫的代碼中所見到的不規(guī)范但偶爾又很微妙的問題。本文的目的是為了幫助那些新手開發(fā)者渡過寫出丑陋的Python代碼的階段。對于那些新手開發(fā)者,總有一些使用反模式的理由,AQFer已經(jīng)嘗試在可能的地方給出了這些理由。但通常這些反模式會造成代碼缺乏可讀性、更容易出bug且不符合Python的代碼風格。

  迭代

  range的使用

  Python編程新手喜歡使用range來實現(xiàn)簡單的迭代,在迭代器的長度范圍內(nèi)來獲取迭代器中的每一個元素:

  python編程

  應該牢記:range并不是為了實現(xiàn)序列簡單的迭代。相比那些用數(shù)字定義的for循環(huán),雖然用range實現(xiàn)的for循環(huán)顯得很自然,但是用在序列的迭代上卻容易出bug,而且不如直接構造迭代器看上去清晰:

  python編程

  range的濫用容易造成意外的大小差一(off-by-one)錯誤,這通常是由于編程新手忘記了range生成的對象包括range的第一個參數(shù)而不包括第二個,類似于java中的substring和其他眾多這種類型的函數(shù)。那些認為沒有超出序列結(jié)尾的編程新手將會制造出bug:

  python編程

  不恰當?shù)厥褂胷ange的常見理由:

  1.需要在循環(huán)中使用索引。

  這并不是一個合理的理由,可以用以下方式代替使用索引:

  Python編程

  2.需要同時迭代兩個循環(huán),用同一個索引來獲取兩個值。

  這種情況下,可以用zip來實現(xiàn):

  Python編程

  3.需要迭代序列的一部分。在這種情況下,僅需要迭代序列切片就可以實現(xiàn),注意添加必要的注釋注明用意:

  Python編程

  有一個例外:

  當你迭代一個很大的序列時,切片操作引起的開銷就比較大。

  如果序列只有10個元素,就沒有什么問題;但是如果有1000萬個元素時,或者在一個性能敏感的內(nèi)循環(huán)中進行切片操作時,開銷就變得非常重要了。

  這種情況下可以考慮使用xrange代替range [1]。

  在用來迭代序列之外,range的一個重要用法是當你真正想要生成一個數(shù)字序列而不是用來生成索引:

  Python編程

  正確使用列表解析

  如果你有像這樣的一個循環(huán):

  Python編程

  你可以使用列表解析來重寫:

  Python編程

  為什么要這么做?

  一方面你避免了正確初始化列表可能帶來的錯誤,另一方面,這樣寫代碼讓看起來很干凈,整潔。

  對于那些有函數(shù)式編程背景的人來說,使用map函數(shù)可能感覺更熟悉,但是在我看來這種做法不太Python化。

  其他的一些不使用列表解析的常見理由:

  1. 需要循環(huán)嵌套。

  這個時候你可以嵌套整個列表解析,或者在列表解析中多行使用循環(huán):

  Python編程

  使用列表解析:

  Python編程

  注意:在有多個循環(huán)的列表解析中,循環(huán)有同樣的順序就像你并沒有使用列表解析一樣。

  2. 你在循環(huán)內(nèi)部需要一個條件判斷。

  你只需要把這個條件判斷添加到列表解析中去:

  Python編程

  一個不使用列表解析的合理的理由是你在列表解析里不能使用異常處理。

  如果迭代中一些元素可能引起異常,你需要在列表解析中通過函數(shù)調(diào)用轉(zhuǎn)移可能的異常處理,或者干脆不使用列表解析。

  性能缺陷

  在線性時間內(nèi)檢查內(nèi)容

  在語法上,檢查list或者set/dict中是否包含某個元素表面上看起來沒什么區(qū)別,但是表面之下卻是截然不同的。

  如果你需要重復檢查某個數(shù)據(jù)結(jié)構里是否包含某個元素,較好使用set來代替list。(如果你想把一個值和要檢查的元素聯(lián)系起來,可以使用dict;這樣同樣可以實現(xiàn)常數(shù)檢查時間。)

  Python編程

  Python中set的元素和dict的鍵值是可哈希的,因此查找起來時間復雜度為O(1)。

  應該記?。?/p>

  創(chuàng)建set引入的是一次性開銷,創(chuàng)建過程將花費線性時間即使成員檢查花費常數(shù)時間。

  因此如果你需要在循環(huán)里檢查成員,較好先花時間創(chuàng)建set,因為你只需要創(chuàng)建一次。

  變量泄露

  循環(huán)

  通常說來,在Python中,一個變量的作用域比你在其他語言里期望的要寬。

  例如:在Java中下面的代碼將不能通過編譯:

  Python編程

  然而在Python中,同樣的代碼總會順利執(zhí)行且得到意料中的結(jié)果:

  Python編程

  這段代碼將會正常運行,除非子y為空的情況下,此時,循環(huán)永遠不會執(zhí)行,而且processList函數(shù)的調(diào)用將會拋出NameError異常,因為idx沒有定義。

  如果你使用Pylint代碼檢查工具,將會警告:使用可能沒有定義的變量idx。

  解決辦法永遠是顯然的,可以在循環(huán)之前設置idx為一些特殊的值,這樣你就知道如果循環(huán)永遠沒有執(zhí)行的時候你將要尋找什么。

  這種模式叫做哨兵模式。那么什么值可以用來作為哨兵呢?

  在C語言時代或者更早,當int統(tǒng)治編程世界的時候,對于需要返回一個期望的錯誤結(jié)果的函數(shù)來說為通用的模式為返回-1。

  例如,當你想要返回列表中某一元素的索引值:

  Python編程

  通常情況下,在Python里None是一個比較好的哨兵值,即使它不是一貫地被Python標準類型使用(例如:str.find [2])

  外作用域

  Python程序員新手經(jīng)常喜歡把所有東西放到所謂的外作用域——python文件中不被代碼塊(例如函數(shù)或者類)包含的部分。

  外作用域相當于全局命名空間;為了這部分的討論,你應該假設全局作用域的內(nèi)容在單個Python文件的任何地方都是可以訪問的。

  對于定義整個模塊都需要去訪問的在文件頂部聲明的常量,外作用域顯得非常強大。

  給外作用域中的任何變量使用有特色的名字是明智的做法,例如,使用IN_ALL_CAPS 這個常量名。 這將不容易造成如下bug:

  Python編程

  如果你看的近一點,你將看到print_file函數(shù)的定義中用filenam命名參數(shù)名,但是函數(shù)體卻引用的卻是filename。

  然而,這個程序仍然可以運行得很好。

  為什么呢?

  在print_file函數(shù)里,當一個局部變量filename沒有被找到時,下一步是在全局作用域中去尋找。

  由于print_file的調(diào)用在外作用域中(即使有縮進),這里聲明的filename對于print_file函數(shù)是可見的。

  那么如何避免這樣的錯誤呢?

  首先,在外作用域中不是IN_ALL_CAPS這樣的全局變量就不要設置任何值[3]。

  參數(shù)解析較好交給main函數(shù),因此函數(shù)中任何內(nèi)部變量不在外作用域中存活。

  這也提醒人們關注全局關鍵字global。如果你只是讀取全局變量的值,你就不需要全局關鍵字global。

  你只有在想要改變?nèi)肿兞棵玫膶ο髸r有使用global關鍵字的必要。

  代碼風格

  向PEP8致敬

  PEP 8是Python代碼的通用風格指南,你應該牢記在心并且盡可能去遵循它,盡管一些人有充分的理由不同意其中一些細小的風格,例如縮進的空格個數(shù)或使用空行。

  如果你不遵循PEP8,你應該有除“我只是不喜歡那樣的風格”之外更好的理由。下邊的風格指南都是從PEP8中摘取的,似乎是編程者經(jīng)常需要牢記的。

  測試是否為空

  如果你要檢查一個容器類型(例如:列表,詞典,集合)是否為空,只需要簡單測試它而不是使用類似檢查len(x)>0這樣的方法:

  Python編程

  如果你想在其他地方保存positive_numbers是否為空的結(jié)果,可以使用bool(positive_number)作為結(jié)果保存;bool用來判斷if條件判斷語句的真值。

  測試是否為None

  如前面所提到,None可以作為一個很好的哨兵值。那么如何檢查它呢?

  如果你明確的想要測試None,而不只是測試其他一些值為False的項(如空容器或者0),可以使用:

  Python編程

  如果你使用None作為哨兵,這也是Python風格所期望的模式,例如在你想要區(qū)分None和0的時候。

  如果你只是測試變量是否為一些有用的值,一個簡單的if模式通常就夠用了:

  Python編程

  例如:如果期望x是一個容器類型,但是x可能作另一個函數(shù)的返回結(jié)果值變?yōu)镹one,你應該立即考慮到這種情況。你需要留意是否改變了傳給x的值,否則可能你認為True或0. 0是個有用的值,程序卻不會按照你想要的方式執(zhí)行。python金融應用實戰(zhàn)適合那些小白入門或者新手入門的童鞋們,感興趣的點擊了解哈~

  附上GIF動圖,更加直觀的了解到Python應用的奇妙之處~還有,祝大家學習愉快~

  量化金融分析師AQF

  量化金融分析師AQF

  往期精彩回顧:

  量化金融分析師AQF丨金融數(shù)據(jù)獲取之tushare(上)

  Python丨金融數(shù)據(jù)獲取之tushare (下)

  金程推薦: AQF考試 AQF報名 量化金融分析師

  量化金融分析師AQF交流答疑群:737550026

  聲明▎更多內(nèi)容請關注微信號量化金融分析師。原創(chuàng)文章,歡迎分享,若需引用或轉(zhuǎn)載請保留此處信息。

  >>>返回首頁

吐槽

對不起!讓你吐槽了

/500

上傳圖片

    可上傳3張圖片

    2001-2026 上海金程教育科技有限公司 All Rights Reserved. 信息系統(tǒng)安全等級:三級
    中央網(wǎng)信辦舉報中心 上海市互聯(lián)網(wǎng)舉報中心 不良信息舉報郵箱:law@gfedu.net
    滬ICP備14042082號 滬B2-20240743 通過ISO9001:2015 國際質(zhì)量管理體系認證 滬公網(wǎng)安備31010902103762號 出版物經(jīng)營許可證 電子營業(yè)執(zhí)照

    掃描二維碼登錄金程網(wǎng)校

    請使用新版 金程網(wǎng)校APP 掃碼完成登錄

    登錄即同意金程網(wǎng)校協(xié)議及《隱私政策》