大多數python開發人員具有不同的核心編程語言背景,例如java,C#或c ++, 因此,他們習慣于用艱苦的方式做事,而當它們以簡單易學的Python語言被引入時,它們會誤解Python的多樣性和功能,并常常最終導致自己誤導其失去某些細微之處,
很多人學習python,不知道從何學起,
很多人學習python,掌握了基本語法過后,不知道在哪里尋找案例上手,
很多已經做案例的人,卻不知道如何去學習更加高深的知識,
那么針對這三類人,我給大家提供一個好的學習平臺,免費領取視頻教程,電子書籍,以及課程的源代碼!
QQ群:961562169
在本文中,我將嘗試解決Python程式員遇到的錯誤, 這些錯誤甚至是本文中的大多數錯誤都是針對中級甚至專家級的開發人員的, 想知道? 如果您是初學者或中級開發人員,請繼續閱讀文章Python開發人員最常犯的10個錯誤,因為當前文章適合更高級的讀者,

1.遍歷串列時修改串列
這是每個Python開發人員一生中至少面對一次的問題,在下面的代碼片段中查看問題:
>>> odd = lambda x : bool(x % 2)
>>> numbers = [n for n in range(10)]
>>> for i in range(len(numbers)):
... if odd(numbers[i]):
... del numbers[i] # 在串列上進行迭代時洗掉串列中的專案...Traceback (most recent call last): File "<stdin>", line 2, in <module>
IndexError: list index out of range
這個問題非常明顯,但即使是高級開發人員,在復雜的作業流程中添加代碼時也會犯類似的錯誤,
有幾種解決方案,我想在這里討論一個最佳解決方案,但據我說這是最簡單的解決方案,因此我不太可能產生錯誤,我建議串列理解在這種情況下非常有用,看看上面的代碼具有串列理解的實作:
>>> odd = lambda x : bool(x % 2)
>>> numbers = [n for n in range(10)]
>>> numbers[:] = [n for n in numbers if not odd(n)]
>>> numbers
[0, 2, 4, 6, 8]
2.創建回圈模塊依賴項
假設您有兩個檔案a.py和b.py,每個檔案都匯入另一個檔案,如下所示:
在a.py中:
import b
def f(): return b.x
print f()
在b.py中:
import a
x = 1
def g():
print a.f()
首先,讓我們嘗試匯入a.py:
>>> import a
1
一切正常,沒有錯誤,它應該給您一個錯誤,但是這里的問題是,如果存在回圈依賴關系,您有時可以擺脫它,因為python足夠聰明,可以跟蹤匯入的軟體包,當每個模塊嘗試訪問另一個模塊的功能時會發生問題,因為不會宣告另一個模塊,這將導致AttributeError,如下所示:
>>> import b
Traceback (most recent call last): File "<stdin>", line 1, in <module>
File "b.py", line 1, in <module>
import a
File "a.py", line 6, in <module>
print f()
File "a.py", line 4, in f
return b.x
AttributeError: 'module' object has no attribute 'x'
要解決此問題,我們需要在函式內部匯入其他依賴模塊:
x = 1
def g(): import a # 僅在呼叫g()時才會計算
print a.f()
現在一切都應該運行良好:
>>> import b
>>> b.g()1 #自模塊'a'在最后呼叫'print f()'以來首次列印
1 #第二次列印,這是我們對“ g”的呼叫
3.錯誤使用運算式作為函式引數的默認值
這是很難除錯的錯誤之一,因為它不會給您帶來錯誤,而且在大多數情況下它可以正常作業,并且開發人員可以擺脫它,當我們可以指定一個可變的可選函式引數時,就會發生這種情況,例如:
>>> def foo(bar=[]):
... bar.append("baz")
... return bar
看起來我們已經創建了一個函式,該函式會將baz附加在指定給它的串列的末尾,否則每次在不使用bar引數的情況下呼叫它都將回傳[“ baz”],因為bar將被初始化為[],但是,當我們執行它時,我們得到以下結果:
>>> foo()
["baz"]
>>> foo()
["baz", "baz"]
>>> foo()
["baz", "baz", "baz"]
輸出結果并非預期的那樣,現在您將看到,如果沒有人注意到此問題,那么如果呼叫它,大多數開發人員將如何擺脫它,通過查看代碼,很難找到尚未遇到此問題或不知道Python如何評估函式的人,因為每次它將bar的值初始化為[]時,都很難,但是在Python中,默認引數僅被評估一次,因此在第一次呼叫時它會按預期作業,但是在第二次和第三次呼叫中,它使用現有的條形串列而不是對其進行初始化,她是我們如何解決這個問題的方法:
>>> def foo(bar=None):
... if bar is None: #或者 if not bar:
... bar = []
... bar.append("baz")
... return bar
...>>> foo()["baz"]
>>> foo()["baz"]
>>> foo()["baz"]
4.錯誤使用類變數
考慮以下示例:
>>> class A(object):
... x = 1
...
>>> class B(A):
... pass
...>>> class C(A):
... pass
...>>> print A.x, B.x, C.x
1 1 1
這個說得通,
>>> B.x = 2
>>> print A.x, B.x, C.x
1 2 1
再次如預期
>>> A.x = 3
>>> print A.x, B.x, C.x
3 2 3
什么?通過更改A類的值,C類不會受到影響是很奇怪的,這是因為在Python中,類變數在內部作為字典處理,并且遵循稱為“方法決議順序”的順序,發生這種情況是因為在類C中找不到屬性x,所以在基類A中對其進行了查找,
5.為例外塊指定不正確的引數
對于給定的代碼:
>>> try:
... l = ["a", "b"]
... int(l[2])
... except ValueError, IndexError: # To catch both exceptions, right?
... pass...Traceback (most recent call last): File "<stdin>", line 3, in <module>
IndexError: list index out of range
追溯(最近一次通話): <模塊>中第3行的檔案“ <stdin>”
IndexError:串列索引超出范圍
看來您正在嘗試捕獲這兩個例外,但這是行不通的,此錯誤通常是由來自python 2.x背景的開發人員犯的,因為在Python 2中,此語法用于將例外系結到可選引數,我們的代碼應該捕獲了IndexError例外,正確的方法是使用元組,方法是指定要在元組中捕獲并使用as系結到引數的所有例外, python 2&3也支持此語法:
>>> try:
... l = ["a", "b"]
... int(l[2])
... except (ValueError, IndexError) as e:
... pass
...>>>
6.對Python作用域規則的誤解
Python范圍決議基于所謂的LEGB規則,它是Local,Enclosing,Global,Built-in的簡寫,但這會使開發人員遇到麻煩,例如:
>>> x = 10
>>> def foo():
... x += 1
... print x...>>> foo()Traceback (most recent call last): File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'x' referenced before assignment
追溯(最近一次通話):
<模塊>中第1行的檔案“ <stdin>”
檔案“ <stdin>”,第2行,在foo中
UnboundLocalError:分配前已參考區域變數“ x”
沒道理我們已經宣告x應該可以正常運行,呼叫該函式會在這里尋找變數x,但找不到變數x,它將把它帶到外部作用域,直到我們對其進行分配之前,它都可以正常作業,我們得到UnboundLocalError以避免函式意外更改變數的值,有關更多資訊,請參見此處,
為了進一步說明,下面是一些其他示例:
>>> lst = [1, 2, 3]
>>> def foo1():
... lst.append(5)
...>>> foo1()>>> lst[1, 2, 3, 5]
>>> lst = [1, 2, 3]
>>> def foo2():
... lst += [5]
...>>> foo2()Traceback (most recent call last): File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in foo
UnboundLocalError: local variable 'lst' referenced before assignment
追溯(最近一次通話):
<模塊>中第1行的檔案“ <stdin>”
檔案“ <stdin>”,行2,在foo中
UnboundLocalError:分配前已參考區域變數“ lst”
在這兩種情況下,我們都嘗試從外部范圍更新串列,在第一個示例中它起作用了,但是在第二個示例中卻沒有起作用,因為我們在函式主體中的該串列上使用了賦值運算子,這將嘗試將計算/評估的值存盤到foo2中不存在的區域變數lst中,
7.混淆Python如何在閉包中系結變數
考慮以下示例:、
>>> def create_multipliers():
... return [lambda x : i * x for i in range(5)]
>>> for multiplier in create_multipliers():
... print multiplier(2)
...
您可能期望以下輸出:
0 2 4 6 8
但是您實際上得到:
8 8 8 8 8
由于Python的后期系結行為,即在呼叫內部函式時會搜索閉包中使用的變數的值,因此,在上面的代碼中,無論何時呼叫任何回傳的函式,i的值都會在呼叫時在周圍的范圍內進行搜索,但是到發生這種情況時,回圈就完成了,因此我已經為其分配了i最終值為4,一種解決方法是:
>>> def create_multipliers():
... return [lambda x, i=i : i * x for i in range(5)]
...>>> for multiplier in create_multipliers():
... print multiplier(2)
...
0
2
4
6
8
8.重新發明輪子
這是在來自低級語言背景(例如c ++,c#等)的開發人員中最常見的,由于龐大的社區和大量的開放源代碼內容以及對python社區的幫助,如果沒有現有的解決方案,很難發現問題,但是在這里,我談論的是重新創建python提供的基礎,其中一些可能包括使用裝飾器,生成器,內置函式,我最好的例子是排序功能,當我為開發人員撰寫滿足其獨特需求的自定義排序函式時,我已經看到了好幾次,在所有情況下,整個功能都可以用更簡單,更優雅和更強大的代碼代替:
list.sort(key=…, reverse=…)
很難找到無法解決我們問題的實際方案,我們甚至可以使用此方法對元組,字典或任何Python物件進行排序,
看下面的例子:
>>> vowels = ['e', 'a', 'u', 'o', 'i']
>>> vowels.sort(reverse=True)
>>> print('Sorted list (in Descending):', vowels)
Sorted list (in Descending): ['u', 'o', 'i', 'e', 'a']
這是元組串列的示例
# take second element for sort#將第二個元素進行排序
def takeSecond(elem): return elem[1]
# random list#隨機串列
random = [(2, 2), (3, 4), (4, 1), (1, 3)]
# sort list with key#用鍵排序串列
random.sort(key=takeSecond)
# print list#列印清單
print('Sorted list:', random)
Output: Sorted list: [(4, 1), (2, 2), (1, 3), (3, 4)]
總結:
即使python很容易上手,但對所使用的工具或范例缺乏深入的了解也會使您陷入麻煩,我希望你們中的一些人會發現
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/119906.html
標籤:Python
上一篇:從無到有,電腦小白學python
