大多數(shù)python開(kāi)發(fā)人員具有不同的核心編程語(yǔ)言背景,例如java网严,CJ队#或c ++。 因此,他們習(xí)慣于用艱苦的方式做事怜庸,而當(dāng)它們以簡(jiǎn)單易學(xué)的Python語(yǔ)言被引入時(shí)当犯,它們會(huì)誤解Python的多樣性和功能,并常常最終導(dǎo)致自己誤導(dǎo)其失去某些細(xì)微之處割疾。
在本文中嚎卫,我將嘗試解決Python程序員遇到的錯(cuò)誤。 這些錯(cuò)誤甚至是本文中的大多數(shù)錯(cuò)誤都是針對(duì)中級(jí)甚至專家級(jí)的開(kāi)發(fā)人員的宏榕。 想知道拓诸? 如果您是初學(xué)者或中級(jí)開(kāi)發(fā)人員,請(qǐng)繼續(xù)閱讀文章Python開(kāi)發(fā)人員最常犯的10個(gè)錯(cuò)誤麻昼,因?yàn)楫?dāng)前文章適合更高級(jí)的讀者奠支。
?
1.遍歷列表時(shí)修改列表
這是每個(gè)Python開(kāi)發(fā)人員一生中至少面對(duì)一次的問(wèn)題。在下面的代碼片段中查看問(wèn)題:
?
這個(gè)問(wèn)題非常明顯抚芦,但即使是高級(jí)開(kāi)發(fā)人員倍谜,在復(fù)雜的工作流程中添加代碼時(shí)也會(huì)犯類似的錯(cuò)誤。
有幾種解決方案叉抡。我想在這里討論一個(gè)最佳解決方案尔崔,但據(jù)我說(shuō)這是最簡(jiǎn)單的解決方案,因此我不太可能產(chǎn)生錯(cuò)誤卜壕。我建議列表理解在這種情況下非常有用您旁±映#看看上面的代碼具有列表理解的實(shí)現(xiàn):
?
2.創(chuàng)建循環(huán)模塊依賴項(xiàng)
假設(shè)您有兩個(gè)文件a.py和b.py轴捎,每個(gè)文件都導(dǎo)入另一個(gè)文件,如下所示:
在a.py中:
?
在b.py中:
?
首先蚕脏,讓我們嘗試導(dǎo)入a.py:
?
一切正常侦副,沒(méi)有錯(cuò)誤。它應(yīng)該給您一個(gè)錯(cuò)誤驼鞭,但是這里的問(wèn)題是秦驯,如果存在循環(huán)依賴關(guān)系,您有時(shí)可以擺脫它挣棕,因?yàn)閜ython足夠聰明译隘,可以跟蹤導(dǎo)入的軟件包。當(dāng)每個(gè)模塊嘗試訪問(wèn)另一個(gè)模塊的功能時(shí)會(huì)發(fā)生問(wèn)題洛心,因?yàn)椴粫?huì)聲明另一個(gè)模塊固耘,這將導(dǎo)致AttributeError,如下所示:
?
要解決此問(wèn)題词身,我們需要在函數(shù)內(nèi)部導(dǎo)入其他依賴模塊:
?
現(xiàn)在一切都應(yīng)該運(yùn)行良好:
?
3.錯(cuò)誤使用表達(dá)式作為函數(shù)參數(shù)的默認(rèn)值
這是很難調(diào)試的錯(cuò)誤之一厅目,因?yàn)樗粫?huì)給您帶來(lái)錯(cuò)誤,而且在大多數(shù)情況下它可以正常工作,并且開(kāi)發(fā)人員可以擺脫它损敷。當(dāng)我們可以指定一個(gè)可變的可選函數(shù)參數(shù)時(shí)葫笼,就會(huì)發(fā)生這種情況。例如:
?
看起來(lái)我們已經(jīng)創(chuàng)建了一個(gè)函數(shù)拗馒,該函數(shù)會(huì)將baz附加在指定給它的列表的末尾路星,否則每次在不使用bar參數(shù)的情況下調(diào)用它都將返回[“ baz”],因?yàn)閎ar將被初始化為[]诱桂。但是奥额,當(dāng)我們執(zhí)行它時(shí),我們得到以下結(jié)果:
?
輸出結(jié)果并非預(yù)期的那樣访诱,現(xiàn)在您將看到垫挨,如果沒(méi)有人注意到此問(wèn)題,那么如果調(diào)用它触菜,大多數(shù)開(kāi)發(fā)人員將如何擺脫它九榔。通過(guò)查看代碼,很難找到尚未遇到此問(wèn)題或不知道Python如何評(píng)估函數(shù)的人涡相,因?yàn)槊看嗡鼘ar的值初始化為[]時(shí)哲泊,都很難。但是在Python中催蝗,默認(rèn)參數(shù)僅被評(píng)估一次切威,因此在第一次調(diào)用時(shí)它會(huì)按預(yù)期工作,但是在第二次和第三次調(diào)用中丙号,它使用現(xiàn)有的條形列表而不是對(duì)其進(jìn)行初始化先朦。她是我們?nèi)绾谓鉀Q這個(gè)問(wèn)題的方法:
?
4.錯(cuò)誤使用類變量
考慮以下示例:
?
這個(gè)說(shuō)得通。
?
再次如預(yù)期
?
什么犬缨?通過(guò)更改A類的值喳魏,C類不會(huì)受到影響是很奇怪的。這是因?yàn)樵赑ython中怀薛,類變量在內(nèi)部作為字典處理刺彩,并且遵循稱為“方法解析順序”的順序。發(fā)生這種情況是因?yàn)樵陬怌中找不到屬性x枝恋,所以在基類A中對(duì)其進(jìn)行了查找创倔。
5.為異常塊指定不正確的參數(shù)
對(duì)于給定的代碼:
?
看來(lái)您正在嘗試捕獲這兩個(gè)異常,但這是行不通的焚碌。此錯(cuò)誤通常是由來(lái)自python 2.x背景的開(kāi)發(fā)人員犯的畦攘,因?yàn)樵赑ython 2中,此語(yǔ)法用于將異常綁定到可選參數(shù)呐能。我們的代碼應(yīng)該捕獲了IndexError異常念搬。正確的方法是使用元組抑堡,方法是指定要在元組中捕獲并使用as綁定到參數(shù)的所有異常。 python 2&3也支持此語(yǔ)法:
?
6.對(duì)Python作用域規(guī)則的誤解
Python范圍解析基于所謂的LEGB規(guī)則朗徊,它是Local首妖,Enclosing,Global爷恳,Built-in的簡(jiǎn)寫有缆。但這會(huì)使開(kāi)發(fā)人員遇到麻煩,例如:
?
沒(méi)道理我們已經(jīng)聲明x應(yīng)該可以正常運(yùn)行温亲。調(diào)用該函數(shù)會(huì)在這里尋找變量x棚壁,但找不到變量x,它將把它帶到外部作用域栈虚。直到我們對(duì)其進(jìn)行分配之前袖外,它都可以正常工作。我們得到UnboundLocalError以避免函數(shù)意外更改變量的值魂务。有關(guān)更多信息曼验,請(qǐng)參見(jiàn)此處。
為了進(jìn)一步說(shuō)明粘姜,下面是一些其他示例:
?
在這兩種情況下鬓照,我們都嘗試從外部范圍更新列表。在第一個(gè)示例中它起作用了孤紧,但是在第二個(gè)示例中卻沒(méi)有起作用豺裆,因?yàn)槲覀冊(cè)诤瘮?shù)主體中的該列表上使用了賦值運(yùn)算符。這將嘗試將計(jì)算/評(píng)估的值存儲(chǔ)到foo2中不存在的局部變量lst中号显。
7.混淆Python如何在閉包中綁定變量
考慮以下示例:
?
您可能期望以下輸出:
?
但是您實(shí)際上得到:
?
由于Python的后期綁定行為臭猜,即在調(diào)用內(nèi)部函數(shù)時(shí)會(huì)搜索閉包中使用的變量的值。因此咙轩,在上面的代碼中获讳,無(wú)論何時(shí)調(diào)用任何返回的函數(shù),i的值都會(huì)在調(diào)用時(shí)在周圍的范圍內(nèi)進(jìn)行搜索活喊,但是到發(fā)生這種情況時(shí),循環(huán)就完成了量愧,因此我已經(jīng)為其分配了i最終值為4钾菊。一種解決方法是:
?
8.重新發(fā)明輪子
這是在來(lái)自低級(jí)語(yǔ)言背景(例如c ++,c#等)的開(kāi)發(fā)人員中最常見(jiàn)的偎肃。由于龐大的社區(qū)和大量的開(kāi)放源代碼內(nèi)容以及對(duì)python社區(qū)的幫助煞烫,如果沒(méi)有現(xiàn)有的解決方案,很難發(fā)現(xiàn)問(wèn)題累颂。但是在這里滞详,我談?wù)摰氖侵匦聞?chuàng)建python提供的基礎(chǔ)凛俱。其中一些可能包括使用裝飾器,生成器料饥,內(nèi)置函數(shù)蒲犬。我最好的例子是排序功能。當(dāng)我為開(kāi)發(fā)人員編寫滿足其獨(dú)特需求的自定義排序函數(shù)時(shí)岸啡,我已經(jīng)看到了好幾次原叮。在所有情況下,整個(gè)功能都可以用更簡(jiǎn)單巡蘸,更優(yōu)雅和更強(qiáng)大的代碼代替:
?
很難找到無(wú)法解決我們問(wèn)題的實(shí)際方案奋隶。我們甚至可以使用此方法對(duì)元組,字典或任何Python對(duì)象進(jìn)行排序悦荒。
看下面的例子:
?
這是元組列表的示例
?
總結(jié):
即使python很容易上手唯欣,但對(duì)所使用的工具或范例缺乏深入的了解也會(huì)使您陷入麻煩。我希望你們中的一些人會(huì)發(fā)現(xiàn)
此文轉(zhuǎn)載文搬味,著作權(quán)歸作者所有黍聂,如有侵權(quán)聯(lián)系小編刪除!
原文地址:https://www.tuicool.com/articles/rY7nQjE
需要源代碼的點(diǎn)擊這里進(jìn)行下載