摘要:編程規(guī)范筆記上寫在前面從語言開始,自己陸續(xù)學(xué)習(xí)了,但是自從研究生做畢設(shè)接觸以來,就愛不釋手,再也沒有動力嘗試其他語言。一與的一大優(yōu)勢就是具備優(yōu)秀的可讀性,而這基于一套較為完整的公認(rèn)編程規(guī)范。如原本希望的結(jié)果是,結(jié)果卻完全一樣。
Python編程規(guī)范筆記(上) 寫在前面:
從C語言開始,自己陸續(xù)學(xué)習(xí)了C++/Java,但是自從研究生做畢設(shè)接觸Python以來,就愛不釋手,再也沒有動力嘗試其他語言。然而慚愧的是,由于一直從事科研工作,因?yàn)楹苌訇P(guān)注代碼規(guī)范性與代碼效率,導(dǎo)致自己之前論文所做實(shí)驗(yàn)代碼可讀性極差。故而忙里抽閑得一半日,粗?jǐn)垺禤ython編程之美》,收貨頗豐,故而重做于屏幕前,權(quán)當(dāng)整理記錄。由于全書于己涉及知識點(diǎn)不少,故而僅挑選當(dāng)前急用者梳理之。
一、PEP_8與PEP_20Python的一大優(yōu)勢就是具備優(yōu)秀的可讀性,而這基于一套較為完整的公認(rèn)編程規(guī)范。這里建議所有初學(xué)或使用Python的同學(xué),可以先從PEP_8入手,其中包括了命名、空格、換行以及函數(shù)參數(shù)等多個最常用最基本的編程規(guī)范。
以自己為例,通常命名變量都采取大小寫組合的形式,如一個表示用戶特征的變量,通常會命名為Users_Feats_lst,而閱讀了PEP_8之后才發(fā)覺這樣寫十分不美觀,導(dǎo)致讀起來十分混亂,推薦的命名規(guī)范是:
常量可以采用全大寫;
類名可以采用HelloWorld的單詞首字母大寫形式;
其余函數(shù)與變量名,全部推薦采用小寫形式;
上面是自己初讀完PEP_8立刻就用上的一點(diǎn)小規(guī)范,感覺很實(shí)用。因此建議大家在開始Python前抽出十分鐘先讀讀PEP_8/20,后者是對于前者的一個擴(kuò)充升級,不過我建議初學(xué)的同學(xué)先從8開始就可以了,逐步學(xué)習(xí)即可。
PEP8 -- Python代碼樣式指南(中文版)
這部分我們就開始梳理感覺最實(shí)用的規(guī)范了。
2.1 明確勝于隱晦Python中提供了同一功能的多種編碼實(shí)現(xiàn)方式,那么越明確越簡練的方式就越推薦。判斷代碼寫得是否優(yōu)雅的一個經(jīng)驗(yàn)法則是:其他開發(fā)者是否可以只閱讀函數(shù)的首行與末行就理解函數(shù)的作用。
2.2 留白勝于緊湊Python一般要求一行僅寫一個語義句,避免多步處理寫在同一行;當(dāng)然,如果一個長參數(shù)函數(shù)可以在函數(shù)部分?jǐn)嘈?,如使用反斜?*或者小括號。
2.3 盡量僅在一處返回函數(shù)結(jié)果當(dāng)遇到多情況的if-else判斷時,往往可以在每個判斷后返回結(jié)果,然而這與具有多重出口的迷宮一樣,會降低可讀性,故而一般要求函數(shù)寫成僅有一個返回return的形式。
對于和邏輯變量以及0比較的情況,相等性檢查全部建議替換為直接使用if語句,如下述情況就推薦2)的形式。
1)if flag_0 == True: pass 2)if flag_0: pass3.2 操作列表(列表解析與filter/map函數(shù))
一般而言循環(huán)操作列表時我們都喜歡使用以下方法,如從下述列表中篩選出大于等于4的元素:
a = range(10) b = [] for ele in a: if a > 4: b.append(ele) else: continue print b
然而,現(xiàn)在我們要推薦一種更為簡潔優(yōu)美的方法:列表解析
a = range(10) b = [i + 2 for i in a if i > 4] print b -->[7, 8, 9, 10, 11]
即,我們只要遵循格式[ele operator | ele from where | ele condation]即可,進(jìn)一步地,上述代碼結(jié)果說明不僅可以設(shè)置篩選特定條件的元素,進(jìn)一步還可以對每個元素進(jìn)行運(yùn)算。
當(dāng)然,如果上面的公式你感覺別扭不容易讀,那么也可以使用同樣功能的函數(shù),只是篩選對應(yīng)filter(),運(yùn)算對應(yīng)map(),其中filter函數(shù)返回篩選條件為True的元素組成的新列表,而map函數(shù)返回函數(shù)操作結(jié)果組成的新列表。
c = filter(lambda x : x > 4, a) print c -->[5, 6, 7, 8, 9] d = map(lambda x : x * x, a) print d -->0, 1, 4, 9, 16, 25, 36, 49, 64, 81]3.3 解包
解包操作主要用于已知列表或者元祖長度的情況下分配元素,其一般通用公式為:
taget_1, taget_2,...,target_N=長度N的列表或者元祖
需要注意的是,僅在Python 3.0以上版本中,才支持可變目標(biāo)參數(shù)的解包(Unpack)
3.4 創(chuàng)建一個包含N個相同對象的列表你可能會想這還不簡單?但是其實(shí)很容易犯錯,我們先給出總結(jié)的規(guī)律:
若非可變對象*N,可以得到正確的N個相同對象的列表
對于空對象[]*N,結(jié)果依舊是空對象[]
對于可變對象[[]]*N,其結(jié)果默認(rèn)是N個指向同一個列表的對象列表
# case 1 four_nones = [None] print four_nones * 4 -->[None, None, None, None] # case 2 four_nones = [] print four_nones * 4 -->[] # case 3 four_nones = [[]] * 4 print four_nones -->[[], [], [], []] four_nones[0].append(1) # still be list, so save the copy attr print four_nones -->[[1], [1], [1], [1]] four_nones[0] = 2 # changed to be integer not list print four_nones -->[2, [1], [1], [1]] # suggest format: 列表解析 four_nones = [[] for i in range(4)] four_nones[0].append(100) print four_nones -->[[100], [], [], []]
所謂陷阱,自然是容易犯錯的部分,這里簡單梳理兩例。
4.1 可變的默認(rèn)參數(shù)有些時候我們希望定義一個可供調(diào)用的函數(shù),其中包含一個可變參數(shù)以適應(yīng)不同調(diào)用場景。如:
# wrong case: def append_to(ele, to=[]): to.append(ele) return to my_list_1 = append_to(10) print my_list_1 -->[10] my_list_2 = append_to(20) print my_list_2 -->[10, 20]
細(xì)心的同學(xué)可能發(fā)現(xiàn)了,我們本希望兩次函數(shù)調(diào)用分別得到[10]與[20],結(jié)果第二次執(zhí)行時卻保留了第一次執(zhí)行的結(jié)果,也就是說,雖然我們使用了可變參數(shù)作為默認(rèn)參數(shù),導(dǎo)致其并未在后續(xù)調(diào)用時刷新。Python在函數(shù)定義而非調(diào)用時自動計算其默認(rèn)參數(shù)。
一個解決的簡單方法是,直接設(shè)置一個默認(rèn)值表示沒有提供默認(rèn)參數(shù),而是每次重新初始化對象:
def append_to(ele, to=None): if to is None: to=[] to.append(ele) return to my_list_1 = append_to(10) print my_list_1 -->[10] my_list_2 = append_to(20) print my_list_2 -->[20]4.2 延遲綁定的閉包
有些時候,我們希望可以采用循環(huán)的方式創(chuàng)建多個唯一性函數(shù),而這時候其中的循環(huán)變量帶來的延遲綁定可能導(dǎo)致錯誤。如:
# wrong case: def create_multipliers(): return [lambda x : x * i for i in range(5)] for multiplier in create_multipliers(): print multiplier(2) -->8 -->8 -->8 -->8 -->8
原本希望的結(jié)果是[0,2,4,6,8],結(jié)果卻完全一樣。其原因在于for循環(huán)依次訪問函數(shù)對象列表時,肯定函數(shù)對象生成函數(shù)已經(jīng)完成,返回的函數(shù)對象中i值全部為4,因此導(dǎo)致結(jié)果一致。此時只需要多帶帶綁定一個默認(rèn)參數(shù)i_0,避免受到i值影響即可:
def create_multipliers(): return [lambda x, i_0 = i : x * i_0 for i in range(5)] for multiplier in create_multipliers(): print multiplier(2) -->0 -->2 -->4 -->6 -->8
今天所梳理的部分集中在兩個方面:
列表解析帶來的列表循環(huán)操作的優(yōu)雅表達(dá)法以及創(chuàng)建N個相等對象列表時可能出現(xiàn)的淺復(fù)制問題,列表解析屬于深復(fù)制;
函數(shù)調(diào)用過程中默認(rèn)參數(shù)在定義時初始化而非調(diào)用時初始化,且循環(huán)創(chuàng)建唯一性函數(shù)時容易受到閉包綁定延遲帶來的影響導(dǎo)致程序錯誤;
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/44017.html
摘要:編程書籍的整理和收集最近一直在學(xué)習(xí)深度學(xué)習(xí)和機(jī)器學(xué)習(xí)的東西,發(fā)現(xiàn)深入地去學(xué)習(xí)就需要不斷的去提高自己算法和高數(shù)的能力然后也找了很多的書和文章,隨著不斷的學(xué)習(xí),也整理了下自己的學(xué)習(xí)筆記準(zhǔn)備分享出來給大家后續(xù)的文章和總結(jié)會繼續(xù)分享,先分享一部分的 編程書籍的整理和收集 最近一直在學(xué)習(xí)deep learning深度學(xué)習(xí)和機(jī)器學(xué)習(xí)的東西,發(fā)現(xiàn)深入地去學(xué)習(xí)就需要不斷的去提高自己算法和高數(shù)的能力然后...
摘要:在開發(fā)大型的項(xiàng)目中,可能會使用到管理的模塊化工具。說道,學(xué)習(xí)過的同學(xué)會比較熟悉,是服務(wù)器模塊的規(guī)范,采用了這個規(guī)范。可能是未來模塊化解決方案的首選。 本文章記錄本人在學(xué)習(xí) JavaScript 中理解到的一些東西,加深記憶和并且整理記錄下來,方便之后的復(fù)習(xí)。 在開發(fā)大型的web項(xiàng)目中,可能會使用到管理js的模塊化工具。但是在前端輪子漫天飛的時代。那一款js模塊化工具真正適合我...
閱讀 8892·2021-11-18 10:02
閱讀 2578·2019-08-30 15:43
閱讀 2651·2019-08-30 13:50
閱讀 1363·2019-08-30 11:20
閱讀 2701·2019-08-29 15:03
閱讀 3623·2019-08-29 12:36
閱讀 926·2019-08-23 17:04
閱讀 613·2019-08-23 14:18