999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

淺談如何寫出整潔的Python代碼

2025-01-11 00:00:00石也牧
科技風(fēng) 2025年1期

摘要:很多人在編寫Python代碼時,只注重相關(guān)功能的實現(xiàn),并不關(guān)心代碼的整潔性。當(dāng)軟件的代碼量達(dá)到一定規(guī)模后,不少開發(fā)者感到代碼越來越混亂、越來越難以維護。學(xué)習(xí)Python語言,不能只關(guān)注語法規(guī)則的掌握。通過代碼示例,文章闡述了與提高軟件代碼整潔性相關(guān)的幾個方面內(nèi)容:寫代碼時,要注意可讀性;要撰寫功能單一且功能清晰的函數(shù);應(yīng)充分利用裝飾器、生成器和迭代器等Python獨有的特性,寫出高效的代碼;應(yīng)了解并經(jīng)常使用Python軟件質(zhì)量保證工具Unittest、Pytest、Pylint和Flake8等測試和掃描代碼。

關(guān)鍵詞:編程規(guī)范;代碼可讀性;軟件可維護性;單元測試

BriefDiscussiononHowtoWriteCleanPythonCode

ShiYemu

FacultyofAIinEducation,CentralChinaNormalUniversityHubeiWuhan430079

Abstract:WhenwritingPythoncode,manypeopleonlyfocusontheimplementationofrelatedfunctionsanddonotcareaboutthecleanlinessofthecode.Whentheamount?;ofsoftwarecodereachesacertainscale,manydevelopersfeelthatthecodebecomesincreasinglyconfusinganddifficulttomaintain.WhenlearningthePythonlanguage,youcan'tjustfocusonmasteringthegrammaticalrules.Throughexamples,thisarticleexplainsseveralaspectsrelatedtoimprovingthecleanlinessofsoftwarecode:payattentiontoreadabilitywhilewritingcode;writefunctionswithsingleandclearintention;makefulluseofdecorators,generatorsanditerators,whicharePython'sspecialfeatures,towriteefficientcode;youshouldunderstandandfrequentlyusePythonSWqualityassurancetoolssuchasunittest,pytest,pylintandflake8,etc.,totestandscanyourcode.

Keywords:Programmingspecifications;codereadability;softwaremaintainability;unittest

實現(xiàn)同樣的功能,不同的程序員寫出來的代碼完全不一樣,有的人寫的代碼很長,既不容易讀懂又很難維護,軟件的可維護性差,會降低工作效率,相應(yīng)的項目會越來越難以持續(xù)下去,嚴(yán)重的會導(dǎo)致項目組不得不重新設(shè)計、編寫代碼。有的軟件作者,在不同時期寫的代碼風(fēng)格不一樣。有的項目組,每個人都有自己的風(fēng)格,組內(nèi)風(fēng)格不統(tǒng)一,大家溝通起來不順暢。這些情況的出現(xiàn),都是因為程序員沒有注意到代碼的整潔性。本文通過舉例,論述了為寫出整潔的代碼而需要注意的幾個地方。

1要有好的可讀性

針對邏輯上并不復(fù)雜的功能需求,有的編程者寫的代碼別人很難讀懂,有的人看不明白自己幾個月前寫的代碼,這都是因為代碼的可讀性差。可讀性不好的軟件,維護起來非常不容易。

寫代碼的同時,要寫相應(yīng)的注釋,寫代碼和寫注釋要做到同步;注釋要有一定的占比,不能可有可無;定義函數(shù)的時候,要有函數(shù)功能和各個參數(shù)說明的注釋;定義類的時候,類的每個屬性和方法都要有相應(yīng)的注釋;修改代碼的時候,相應(yīng)的注釋也必須修改。雖然注釋不參與編譯、不參與程序的運行,但注釋非常重要,要把注釋看作是程序的一個組成部分。

除了增加注釋外,文件名、變量名、函數(shù)名和類名等要盡可能地做到顧名思義和一望而知[1],不要讓閱讀代碼的人(包括將來的自己)去猜。例如:

classPerson:

def__init__(self,name,email,phone):

self.name=name

self.email=email

self.phone=phone

顯然,類Person的初始化函數(shù)記錄了人名、郵箱和電話。寫代碼能做到見其名知其意很好,但也不要過度。例如,下面的代碼和前面相比,很詳盡,但并沒有增加可讀性,反而讓人覺得過于啰唆:

classPerson:

def__init__(self,personal_username,personal_email_address,personl_telephone_number):

self.personal_username=personal_username

self.personal_email_address=personal_email_address

self.personal_telephone_num=personal_telephone_number

2函數(shù)功能要單一

假設(shè)有如下函數(shù),功能是取得一個列表,然后打印該列表的所有元素:

deffetch_and_show_users():

users=[…]#由某算法得到列表

foruserinusers:

print(user)#顯示列表

這個函數(shù)有兩個功能,但有的用戶只需要得到列表,而有的用戶只想顯示列表。這時,對于某些調(diào)用該函數(shù)的用戶而言,代碼里出現(xiàn)了累贅,這增加了代碼的冗余,多余的步驟對程序的調(diào)試會造成干擾。把前面的函數(shù)分解為如下的兩個函數(shù),非常方便于用戶的調(diào)用:

deffetch_users():

users=[]#由某算法得到列表

returnusers

defdisplay_users(users):

foruserinusers:

print(user)#顯示列表

再舉個例子,某個函數(shù)具備下載、解壓縮和按照某種規(guī)則選取解壓之后文件的功能,最好將這個函數(shù)分解。否則,可能會出現(xiàn)這樣的情況:有的用戶只是想下載某個壓縮包而調(diào)用了該函數(shù),他不得不等著解壓縮和選取文件這兩個他并不需要的步驟完成。

不僅是函數(shù),還有類和模塊,都應(yīng)功能單一,只做一件事而且要將事情做好[2]。

3函數(shù)功能要清晰

先看如下轉(zhuǎn)換大小寫的函數(shù),該函數(shù)的作用不難理解:

deftransform_text(text,uppercase):

ifuppercase:

returntext.upper()

else:

returntext.lower()

顯然,當(dāng)調(diào)用transform_text(text,True)時,字符串text中的小寫字母都轉(zhuǎn)換為大寫;當(dāng)調(diào)用transform_text(text,F(xiàn)alse)時,字符串text中的大寫字母都轉(zhuǎn)換為小寫。如果不看函數(shù)transform_text的定義,僅僅看transform_text(text,True/False),很難知道它在做什么。

將上面的函數(shù)分為如下兩個函數(shù):

defturn_to_uppercase(text):

returntext.upper()

defturn_to_lowercase(text):

returntext.lower()

當(dāng)調(diào)用turn_to_uppercase(text)時,字符串text中的小寫字母都轉(zhuǎn)換為大寫;當(dāng)調(diào)用turn_to_lowercase(text)時,字符串text中的大寫字母都轉(zhuǎn)換為小寫。這時,僅僅看turn_to_uppercase(text)或者turn_to_lowercase(text),就知道在做什么。函數(shù)的功能要做到清晰明確[3]。

在調(diào)用函數(shù)遇到關(guān)鍵字參數(shù)的時候,帶上關(guān)鍵字名字可以增強可讀性,而且不必?fù)?dān)心參數(shù)的次序?qū)戝e。例如,SendMail(from=a@x.com,to=b@y.com)比SendMail(a@x.com,b@y.com)的可讀性強很多,用意一目了然,就像在讀簡單明了的英文句子。

4使用更Pythonic的語法

Python代碼要有“Python的味道”,同等條件下,代碼要寫得Pythonic一些。例如,遍歷一個列表,可用如下for循環(huán):

forkinrange(len(a_list)):

print('index:',k,'value:',a_list[k])

上面的代碼是正確的,但這是傳統(tǒng)編程語言的方法。作為Python程序員,應(yīng)使用針對可迭代對象的內(nèi)置函數(shù)enumerate:

forindex,iteminenumerate(a_list):

print('index:',index,'value:',item)

交換兩個變量a和b的值,傳統(tǒng)語言的代碼如下:

tmp=b

b=a

a=tmp

Python代碼這樣寫也是沒有問題的。實際上,Python語言有如下簡便的寫法,用以交換a和b的值:

a,b=b,a

判斷字符串的前綴與后綴,可以使用內(nèi)置的字符串方法startswith和endswith,也可以使用切片。例如,如下if語句作用是相同的:

sentence="Helloeveryone,goodmorning"

ifsentence.startswith("Hello"):……

ifsentence[:5]=="Hello":……

ifsentence.endswith("morning"):……

ifsentence[-7:]=="morning":……

很明顯,startswith和endswith的可讀性更好,使用切片的話,可讀性下降,而且容易將字母的個數(shù)寫錯。

對一個列表的每個元素進行相同的操作,使用map和列表推導(dǎo)都可以。例如:

>>>nums=[1,2,3,4,5]

>>>squares=list(map(lambdax:x**2,nums))

>>>squares

[1,4,9,16,25]

>>>squares=[x**2forxinnums]

>>>squares

[1,4,9,16,25]

顯然,列表推導(dǎo)的可讀性更強、形式上簡單,而且列表推導(dǎo)的速度比map快,運行效率高。完成同樣的任務(wù),應(yīng)盡可能使用列表推導(dǎo)而不是map。

5充分利用Python的獨有特性

裝飾器本身是一個函數(shù),裝飾器的返回值是一個函數(shù)對象,裝飾器可以讓其他函數(shù)在不需要做任何代碼變動的前提下增加額外功能[4]。例如,有N個函數(shù),現(xiàn)在要給它們增加函數(shù)日志和函數(shù)性能測試的功能。如果是傳統(tǒng)編程語言,需要對每個函數(shù)進行修改。對于Python而言,不需要進行N次類似甚至同樣的修改。定義一個裝飾器decorator,對函數(shù)進行封裝,添加所需的功能(日志和性能測試),然后在每個函數(shù)的頭部添加一行@decorator即可,N個函數(shù)的原始代碼保持不變。這樣保證了代碼的穩(wěn)定性,在減少重復(fù)勞動的同時,增加了函數(shù)的功能。

生成器支持延遲計算,在需要的時候可以生成相應(yīng)的值,而不是一次性地生成整個序列。生成器特別適合于大型數(shù)據(jù)處理,使用生成器,可以減少內(nèi)存使用,優(yōu)化代碼,提高程序的效率。

6使用Unittest和Pytest進行測試

有的程序員寫了很長時間的代碼,但從未對自己的代碼進行過單元測試,只有在程序運行遇到錯誤時才開始檢查當(dāng)中的問題。單元測試是用來對函數(shù)、類或者模塊進行正確性檢驗的工作[5]。如果代碼都通過了單元測試,那么軟件的質(zhì)量將大大提高。Unittest是Python自帶的測試框架,例如,如下代碼使用斷言來測試函數(shù)square()是否正確:

importunittest

defsquare(a):

returna*a

classST(unittest.TestCase):

deftest_square(self):

self.assertEqual(square(7),49)

if__name__=="__main__":

unittest.main()

Pytest是一個第三方的測試框架,兼容Unittest,比Unittest框架使用起來更簡潔,效率更高,使用命令pipinstallpytest安裝它。Pytest編寫測試用例很容易,用例可以是類的形式,也可以是函數(shù)的形式。例如,如下代碼用來測試函數(shù)double()的正確性:

defdouble(x):

return3*x

deftest_dbl():

assertdouble(8)==16

運行pytest,結(jié)果為:

deftest_dbl():

>assertdouble(8)==16

Eassert24==16

E+where24=double(8)

test.py:4:AssertionError

根據(jù)輸出,很容易看到問題所在,將函數(shù)double()中的3*x改為2*x就解決了。

7使用Pylint等工具檢查代碼

在項目編碼完成或者階段性完成后,應(yīng)該使用質(zhì)量保證工具對代碼進行掃描,就像體檢一樣。Pylint是一個針對Python代碼中的語法錯誤、潛在問題和代碼風(fēng)格的靜態(tài)檢查工具,使用pipinstallpylint命令安裝它。下面的代碼一共三行,看上去沒有任何問題:

defadd_one(x):

returnx+1;

print(add_one(15))

運行命令python3mpylint<文件名>,用Pylint分析這三行看似正確且毫無瑕疵的代碼,得到的結(jié)果為:

2:0:W0311:Badindentation.Found3spaces,expected4(badindentation)

2:0:W0301:Unnecessarysemicolon(unnecessarysemicolon)

1:0:C0114:Missingmoduledocstring(missingmoduledocstring)

1:0:C0116:Missingfunctionormethoddocstring(missingfunctiondocstring)

短短的三行代碼,掃描出了四個問題:(1)第二行的縮進是三個空格,最好是四個空格;(2)第二行結(jié)尾的分號沒有必要;(3)文件沒有注釋說明;(4)函數(shù)也沒有注釋說明。修改如下,再使用Pylint掃描就沒有問題了:

'''Thispythonscriptisforpylintstudy'''

defadd_one(x):

'''inputparameterisanumber,

add1tothenumber,andreturn'''

returnx+1

print(add_one(15))

8學(xué)習(xí)PEP8

除了語法,程序員也要學(xué)習(xí)編碼規(guī)范方面的知識。PEP8是Python編碼規(guī)范指南,PEP是PythonEnhancementProposals的簡寫,遵循該規(guī)范可以讓開發(fā)者寫出整潔的代碼,提高代碼的可讀性,有助于同一個項目組內(nèi)大家的編碼風(fēng)格保持一致[6]。使用工具Pycodestyle可以檢查代碼是否遵從PEP8,運行命令pipinstallpycodestyle安裝它。如下是非常簡短的四行代碼:

a=1

b=2

print(a==b)

if(b>a):print("bisbigger")

運行命令pycodestyle<文件名>,檢測這四行代碼,結(jié)果如下:

1:2:E225missingwhitespacearoundoperator

3:6:E211whitespacebefore'('

4:3:E275missingwhitespaceafterkeyword

4:10:E231missingwhitespaceafter':'

4:10:E701multiplestatementsononeline(colon)

使用Pycodestyle發(fā)現(xiàn)的問題有:a=1的等號兩邊應(yīng)該有空格;print和(之間的空格是不需要的;關(guān)鍵字if的后面應(yīng)該有空格;最后一行最好分為兩行。將代碼修改如下,再使用Pycodestyle掃描就沒有問題了:

a=1

b=2

print(a==b)

ifb>a:

print("bisbigger")

工具Flake8的功能比Pycodestyle更加強大,安裝命令為pipinstallflake8。Flake8將Pyflakes(類似于Pylint)、Pycodestyle和McCabe(代碼復(fù)雜性檢查器)整合到一起,使用它可以一次性檢查出多種問題。Flake8非常易于與其他工具結(jié)合,比如,在集成開發(fā)環(huán)境PyCharm中配置Flake8非常簡單。

結(jié)語

Python誕生于1991年,近些年,Python語言已經(jīng)滲透到各個領(lǐng)域,使用Python的人越來越多。Python用戶不能僅僅學(xué)語法,還應(yīng)該了解如何讓代碼變得更整潔。軟件的維護期一般長于(甚至遠(yuǎn)遠(yuǎn)長于)開發(fā)期,不整潔的代碼很難提高工作效率。作為Python開發(fā)人員,要想寫出整潔的代碼,除了語法規(guī)則之外,需要了解的知識點比較多,很難用一篇短文完全闡述清楚。希望本文能給新Python程序員一點啟發(fā),為代碼質(zhì)量的提升提供些許幫助。

參考文獻:

[1]HarshitTyagi.PythonicCode:BestPracticestoMakeYourPythonMoreReadable[EB/OL].(20220530).https://www.codementor.io/blog/pythoniccode6yxqdoktzt.

[2]AlexOmeyer.10MustKnowPatternsforWritingCleanCodeWithPython[EB/OL].(20220406).https://dzone.com/articles/10mustknowpatternsforwritingcleancodewith1.

[3]KhuyenTran.PythonCleanCode:6BestPracticestoMakeYourPythonFunctionsMoreReadable[EB/OL].(20210121).https://towardsdatascience.com/pythoncleancode6bestpracticestomakeyourpythonfunctionsmorereadable7ea4c6171d60.

[4]蘇尼爾·卡皮爾.Python代碼整潔之道編寫優(yōu)雅的代碼[M].連少華,譯.北京:機械工業(yè)出版社,2020.

[5]馬里西諾·阿納亞.編寫整潔的Python代碼[M].包永帥,譯.北京:人民郵電出版社,2021.

[6]ThePEPEditors.IndexofPythonEnhancementProposals[EB/OL].(20000713).https://peps.python.org/.

作者簡介:石也牧(2004—),女,漢族,北京人,本科,研究方向:人工智能。

主站蜘蛛池模板: h网站在线播放| 99精品伊人久久久大香线蕉| 久久精品国产亚洲麻豆| 成人小视频网| 亚洲香蕉伊综合在人在线| 欧美成人免费一区在线播放| 国产原创演绎剧情有字幕的| 97综合久久| 五月天综合网亚洲综合天堂网| 熟妇人妻无乱码中文字幕真矢织江 | 国产极品粉嫩小泬免费看| 性网站在线观看| 91精品啪在线观看国产60岁| 国产欧美视频综合二区| 欧美精品一区在线看| 四虎永久在线| 精品一区二区三区视频免费观看| 亚洲精品欧美重口| 蜜桃视频一区二区三区| 亚洲人成网站在线播放2019| 亚洲A∨无码精品午夜在线观看| 欧美综合成人| 国产高颜值露脸在线观看| 国产精品va| 成人国产免费| 成年免费在线观看| 欧美亚洲国产精品久久蜜芽| 欧美国产综合色视频| 国产亚洲精品91| 99在线观看免费视频| 九色综合视频网| 国产精品午夜电影| 亚洲国产系列| 国产不卡在线看| 亚洲国产精品日韩专区AV| 中文无码毛片又爽又刺激| 91亚瑟视频| 欧美啪啪一区| 小13箩利洗澡无码视频免费网站| 亚洲三级a| 日韩久草视频| 丁香五月婷婷激情基地| 丁香婷婷久久| 亚洲国产日韩一区| 国产高颜值露脸在线观看| 成人综合久久综合| 91探花国产综合在线精品| 亚洲欧美成人网| 激情无码字幕综合| 成人国产小视频| 999精品免费视频| 精品少妇人妻无码久久| AV在线麻免费观看网站| 91成人免费观看| 久久精品亚洲中文字幕乱码| 2024av在线无码中文最新| 国产精品对白刺激| 欧美精品三级在线| a亚洲天堂| 国产三级成人| 亚洲精品无码久久毛片波多野吉| 亚洲视频影院| a在线亚洲男人的天堂试看| 欧美成人精品一级在线观看| 美女无遮挡免费视频网站| 亚洲国产成人久久77| 国产欧美日韩资源在线观看| 欧美成人午夜视频免看| 国产精品999在线| 亚洲福利视频一区二区| 精品撒尿视频一区二区三区| 欧美激情第一欧美在线| 亚洲成A人V欧美综合| 激情无码字幕综合| 视频在线观看一区二区| 国产欧美日韩18| 久久精品aⅴ无码中文字幕| 国产欧美日韩专区发布| 亚洲大学生视频在线播放| 欧美国产成人在线| 免费国产好深啊好涨好硬视频| 搞黄网站免费观看|