iT邦幫忙

9

【Python 超入門】(5) 淺談Debug(除錯)- 不怕錯誤的勇氣

大家好,我是「心原一馬」,內心原來一心喜歡打程式碼。
今天,不只談技術,更希望能幫助更多想入門程式者建立信心。
很多人初學程式時可能會有這樣的問題:

天啊,我照著網上的教學文打程式,怎麼程式還是出現錯誤訊息?
照著自己的想法打程式,總是跟預想的效果不一樣…
我寫程式常常有錯誤訊息,我是不是不適合寫程式?

如果你也有開始面臨這樣的問題,
我會說這是學習的必經之路。
甚至,初學時,花一整天解決一個簡單的語法錯誤可能也是常有的事。
但別害怕,我們先看下面一個故事:

買十個包子,若看到賣西瓜的就買一個

有一天,老婆打電話給他的工程師老公說:
「親愛的,下班幫我買十個包子,若看到賣西瓜的,就買一個。」
結果工程師下班之後只有買一個包子,老婆很疑惑的問:「怎麼只有買一個包子呢?」
老公說:「因為我看到賣西瓜的。」
這是語義不完整造成的誤解:
老婆的意思是:「買十個包子,若看到賣西瓜的,再多買一個西瓜。」
老公的解讀是:「買十個包子,若看到賣西瓜的,改成買一個包子。」

電腦是忠實的僕人

其實電腦程式在工作上就像這樣,程式會忠實的運行你對它下達的指令,
但是不論是多麼奇怪的指令也會照常執行。
上述的例子,你尚且可以說,
根據日常生活的經驗,我們很難想像為什麼看到賣西瓜的就要少買九個包子,
因此不會解讀成「買十個包子,若看到賣西瓜的,改成買一個包子。」

但是跟電腦溝通就不一樣了,
電腦不會有人類所謂的這種「常識判斷」,
你給電腦下指令一定要非常精確它才會做。

所以…錯誤訊息其實是友善的提示

當你下次可能不小心打出這樣子的程式:

Print("Hello World")

然後看到一堆錯誤訊息:

https://ithelp.ithome.com.tw/upload/images/20190624/201171147UuF5uyjJ0.jpg

的時候,不用再嚇到了,
這兩句 File "C:/Users/User/.spyder-py3/temp.py", line 1, in <module> Print("Hello")
NameError: name 'Print' is not defined
那是電腦友善的提示,
電腦禮貌的告訴你:「不好意思,您的第一行指令語義我不太理解,您下的 Print 指令我好像沒有這個功能耶,請確認一下您是不是名字有打錯呢?」
(可怕的是你以為你叫電腦做一件事,其實它做的是另外一件事~)
我們來看一下幾種常見的錯誤。

簡易除錯表1 - 大小寫有別

以剛剛那個例子,內建函數print都是小寫字母,對程式來說大小寫字母不一樣。

簡易除錯表2 - 字串沒用引號包起來

例如這支程式

print(Hello) # 'Hello'忘記用引號包起來

你希望在螢幕上印出Hello,忘記用引號包起來,程式會以為是不是有一個變數叫做Hello。

簡易除錯表3 - 左右括號沒成對出現

我們看這支程式:

x = 40
y = '60'
print(x+int(y) #希望算出40+60的值

print("Hello")
print("我是可愛的馬")

(給新手: int(變數) 是把一個字串變數或是浮點數變數轉換成整數的意思)
這個錯誤是我覺得對新手來說相對稍難找一點的錯誤。
仔細看程式的第三行少了一個右括號,
正確應為: print(x+int(y)) 才對
但你如果執行這支程式,會看到提示訊息寫說第五行有錯,
如圖:

https://ithelp.ithome.com.tw/upload/images/20190624/20117114UytO3pCQc6.jpg

於是你左看右看上看下看,就是看不出來print("Hello")這一行哪裡錯了。

那麼為什麼是顯示第五行錯呢?
因為左右括號應該是成對出現的,
第三行本來應該有右括號沒寫,
編譯器會認為這一行是不是還沒寫完啊,就往下繼續找,
就找到第五行了。

(2020/3/6補充) 簡易除錯表4- 誤將python內建函數當做變數名稱

python中有一些自帶的內建函式,
例如int, str, 等等…
int(變數) : 是把一個字串變數或是浮點數變數轉換成整數的意思
str(變數) : 是把一個其它型態的變數(如整數)轉換成字串的意思

雖然程式並未禁止將int, str當做變數名稱,
但非常不建議將內建函數當做變數名稱

我們看這樣簡短的程式:

str = "1"
n = 1
print(str(n))

在第一行,將str賦值為"1"
會覆蓋python裡面的str函式,
以致於第三行做str(n)的時候,程式並不認得這個函數,
而會出現TypeError: 'str' object is not callable的錯誤

當你執行過上述程式後,
即使你刪掉第一行,變成:

n = 1
print(str(n))

仍會出現TypeError: 'str' object is not callable的錯誤,
這是因為python裡面的str函式已經被覆蓋掉了,
所以新手可能就會疑惑到底print(str(n))這一行哪裡錯了,
實際上可能是打程式的過程中不小心誤將str當做變數名稱

當碰到這樣的問題時,
以spyder為例,
請在spyder右下角的顯示結果的那個視窗找到
「Restart kernal」選單按下去應該就好了

https://ithelp.ithome.com.tw/upload/images/20200303/201171148lZx1OEJQe.png

或是將直接將spyder標籤上面的叉叉按下去也可
https://ithelp.ithome.com.tw/upload/images/20200306/201171144axfBstEAk.png

好的,以上就是debug一些簡單的介紹了。
喜歡我的文章的話,歡迎順手按like或是追蹤我。


4
1
ZacherySyu
iT邦見習生 ‧ 2019-06-25 18:27:51

非常貼心的提示,謝謝老師!

1
sdhis030
iT邦新手 5 級 ‧ 2019-11-18 16:46:06

比我現在上課的老師所講的內容與脈絡好多了!!! 非常容易理解且吸收 ^_^

心原一馬 iT邦研究生 5 級 ‧ 2019-11-18 22:46:49 檢舉

哈哈,感謝你欣賞小馬的文章哦,很高興有幫到你~

1
medivh0102
iT邦新手 5 級 ‧ 2020-03-06 00:43:31

一馬哥 不好意思跟您請教一下文章內解說的問題,如下:
「那麼為什麼是顯示第五行錯呢?因為左右括號應該是成對出現的,
第三行本來應該有右括號沒寫,編譯器會認為這一行是不是還沒寫完啊,就往下繼續找,
就找到第五行了」

這是一馬哥您於文章末端所寫的,
但我不解的是,第5行程式碼還是沒有錯啊,為什麼編譯器會認為是那邊初錯了呢?
是因為連帶把第3行的括號也一併帶到第5行去算了,所以少一個右括號嗎?

心原一馬 iT邦研究生 5 級 ‧ 2020-03-06 08:59:35 檢舉

您好:
因為程式語言的左右括號必須成對,
所以編譯器會認為底下的程式碼中,

print(x+int(y)

print("Hello")

這句話「x+int(y) print("Hello" 」都是包在左右括號裡面的,
所以會認為是print("Hello"這邊錯了。

就是說如果是解讀成x+int(y) print("Hello"都包在print函數裡面的話會很怪,
int(y) print這樣寫在一起並沒有什麼意思,
所以應該會認為是第五行的錯

原來如此 長知識了 謝謝!

我要留言

立即登入留言