標籤:any 學習編程 需要 一起 初學 jin dirname 字母 更新
Python是一門靈活的,有意思的,用途廣泛的語言。近些年來,收到越來越多的重視。也有越來越多的人來學習這門語言。
於是,問題來了,對於初學者,往往在寫代碼的過程中,出現這樣或那樣的錯誤,導致程式運行報錯。這些錯誤或簡單,或複雜,或詭異,或神奇,要麼令人抓耳撓腮,要麼讓人惱羞成怒,要麼讓人難以忘懷。但是,在學習編程的過程中,就是這些錯誤讓我們成長,讓我們逐漸從采坑再爬坑的過程中,感受到編程的魅力。
到底有哪些錯誤呢,請看DE8UG給你帶來的"Python花式錯誤集錦",如果你遇到了Python開發中的錯誤,從本文搜尋關鍵詞並得到解決,那是我的榮幸。
語法錯誤篇縮排IndentationError
這是在複製粘貼代碼,或者不熟悉Python代碼結構時候,經常範的錯誤。Python中要求同一邏輯的代碼塊使用同樣的縮排(常用4個空格)。
看這段:
def test(): a = 1 b = 2 return a + b
運行後,立馬報錯
File "<ipython-input-1-515579e6247e>", line 4 return a + b ^IndentationError: unindent does not match any outer indentation level
解決方案,很簡單,把縮排調整為統一的4個空格就好。
標點符號SyntaxError
這裡情況就比較多了,常見的為
來看看具體錯誤樣式
def test(): pass File "<ipython-input-2-b5cadef232ad>", line 1 def test(): ^SyntaxError: invalid character in identifierprint(1,2,3,4,5,6) File "<ipython-input-3-be45856da7c7>", line 1 print(1,2,3,4,5,6) ^SyntaxError: invalid character in identifierdef test_a(a): return a * 2def test_b(b): return b + 3def test_c(c): return c - 4x = 5test_c(test_b(test_a))TypeError Traceback (most recent call last)<ipython-input-4-af8d9c054419> in <module>() 9 10 x = 5---> 11 test_c(test_b(test_a))<ipython-input-4-af8d9c054419> in test_b(b) 3 4 def test_b(b):----> 5 return b + 3 6 7 def test_c(c):TypeError: unsupported operand type(s) for +: ‘function‘ and ‘int‘# 還可能這樣test_c(test_b(test_a()) File "<ipython-input-5-eab78f53d59a>", line 11 test_c(test_b(test_a()) ^SyntaxError: unexpected EOF while parsing
修改方式很簡單,代碼裡的標點符號都是英文,出現語法錯誤好好檢查看看標點符號的寬度,我的簡單記法是中文的都比較胖,英文的都是瘦子。另外,對於括弧的問題,首先是要英文,其次呢寫的時候,養成一種上來先把成對()寫好的習慣,然後再填內容。
變數應用篇命名錯誤
最需要禁止的是使用Python內建的關鍵詞來命名,比如list,dict等,會導致類型錯誤。
a = (2,5,8)a_list = list(a) # 第一次可以用list轉換list = list(a) # 如果把list當作變數名,會引起後續代碼再用list轉換時候報錯b = (3,5,7)b_list = list(b)TypeError Traceback (most recent call last)<ipython-input-12-70adb4cffa4f> in <module>() 1 b = (3,5,7)----> 2 b_list = list(b)TypeError: ‘list‘ object is not callable
2b = c File "<ipython-input-7-9b1de15aaa88>", line 1 2b = c ^SyntaxError: invalid syntaxa-2 = 1 File "<ipython-input-8-ac5315177c02>", line 1 a-2 = 1 ^SyntaxError: can‘t assign to operator
命名時候,建議使用底線_連字號,或者theName,或者TheName這種首字母大寫的駝峰法。
而且,不建議使用0(數字零)或者l(小寫L)來命名,否則容易引起下面的使用錯誤。
使用錯誤
這裡最常見的是使用容易混淆的字母來命名,造成似乎用時候出錯,或者是使用時候完全用錯了變數。
name_l = ‘de8ug‘print(name_1)NameError Traceback (most recent call last)<ipython-input-13-cfee4c383b1a> in <module>() 1 name_l = ‘de8ug‘----> 2 print(name_1)NameError: name ‘name_1‘ is not definedname_0 = ‘de8ug‘print(name_o)---------------------------------------------------------------------------NameError Traceback (most recent call last)<ipython-input-14-7b351863596a> in <module>() 1 name_0 = ‘de8ug‘----> 2 print(name_o)name = ‘de8ug‘print(f‘name‘)print(f‘{de8ug}‘)print(f‘{name}‘)NameError Traceback (most recent call last)<ipython-input-17-22b546a709ce> in <module>() 1 name = ‘de8ug‘ 2 print(f‘name‘)----> 3 print(f‘{de8ug}‘) 4 print(f‘{name}‘)NameError: name ‘de8ug‘ is not defined
編碼錯誤篇
Python3中,最常見的編碼錯誤是在網路應用中,有時候得到的資料是bytes,但是我們實際需要str,這時候就需要轉換編碼。
這裡需要注意bytes和str的轉換,其中 encoding=‘utf-8‘是預設的參數
name = "de8ug"print(type(name)) # strprint(type(name.encode())) # bytes, S.encode(encoding=‘utf-8‘, errors=‘strict‘) -> bytesname = b"de8ug"print(type(name)) # bytesprint(type(name.decode())) # str, decode(encoding=‘utf-8‘, errors=‘strict‘) --> str
匯入模組篇
這種情況經常發生在使用某些模組的功能,但是py檔案頭部忘記匯入
json.loads(‘{"name":"de8ug", "city":"beijing"}‘)NameError Traceback (most recent call last)<ipython-input-41-fd9b6a45da38> in <module>()----> 1 json.loads(‘{"name":"de8ug", "city":"beijing"}‘)NameError: name ‘json‘ is not defined
這種情況經常出現在學習某些新內容,學習(chao)完代碼開始運行時候,發現啥啥啥沒defined,這時候就需要去檢查是不是最開始沒有import的問題了。
當加入 import json後,可得到正確結果{‘name‘: ‘de8ug‘, ‘city‘: ‘beijing‘}
- 運行py檔案時候報錯ModuleNotFoundError: No module named ‘xxx‘
這種情況一般是,啟動並執行那個py檔案又需要匯入自己定義的其他模組,
但此時系統不知道哪些模組的存在,解決辦法是在啟動並執行第一個py檔案頭部,添加如下代碼:
這種情況適用於有個project項目,裡面又bin,conf,app等目錄,當bin裡面的py檔案又需要引入conf,app等目錄的模組時候,需要讓系統本身知道project這目錄的存在,先有爺爺,然後才能有孫子啊。
import osimport sysBASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))sys.path.append(BASE_DIR)
函數使用篇
Python在函數中使用變數的時候,會按照LEGB(Local(本地),Enclosing(封閉),Global(全域),Built-in(內建))這種範圍的順序來尋找變數。如果有賦值(給同名的變數)操作,需要確保當前範圍下已經有這個變數。因為這時候Python認為函數內部和外部有同名的變數,會把外部的屏蔽。
name = ‘de8ug‘def say_name(): print(f‘name is: {name}‘)say_name() # 這時候正常, name is: de8ugname = ‘de8ug‘def say_name(): name = name.capitalize() # 把名字大寫,並賦值給name print(f‘name is: {name}‘)say_name()---------------------------------------------------------------------------UnboundLocalError Traceback (most recent call last)<ipython-input-37-05a0d34cba37> in <module>() 4 print(f‘name is: {name}‘) 5 ----> 6 say_name()<ipython-input-37-05a0d34cba37> in say_name() 1 name = ‘de8ug‘ 2 def say_name():----> 3 name = name.capitalize() # 把名字大寫,並賦值給name 4 print(f‘name is: {name}‘) 5 UnboundLocalError: local variable ‘name‘ referenced before assignment這時候提示錯誤,name作為局部變數,在賦值前被引用了。因為和外部變數同名,此時name.capitalize()引用name的時候,在函數內部還沒有name這個變數的具體內容,所以報錯。
修改方式:
直接引用外部變數,使用相應的方法,或者採用不同的變數名
print(f‘name is: {name.capitalize() }‘) # 直接列印或cap_name = name.capitalize()
類似的還有+=的時候,這時候相當於兩部操作,先=後+,但,如果函數內部變數和函數外相同,就會出現類似上面的錯誤。你感受一下:
n = 10def add(): n += 8 print(n)add()---------------------------------------------------------------------------UnboundLocalError Traceback (most recent call last)<ipython-input-46-8215b717b8ed> in <module>() 4 print(n) 5 ----> 6 add()<ipython-input-46-8215b717b8ed> in add() 1 n = 10 2 def add():----> 3 n += 8 4 print(n) 5 UnboundLocalError: local variable ‘n‘ referenced before assignment
小結
ok,最後我們總結一下,常見的錯誤有這麼幾種,
你都犯過了嗎?
聊到最後,有沒有解決你學習Python的過程裡出現的一些錯誤呢?或者,你有沒有遇到過什麼有意思的錯誤呢?歡迎留言討論,一起聊聊。
(首發於公眾號<第8哥小灶時間>,轉載請註明出處)
Python花式錯誤集錦(長期更新)