Python語言要素

要開始設計Python程式的最最基本,一定要知道的地方,老師在這裡簡單地說明一下。

執行程式的地方

在上一個單元教材中,老師列出了許多種可以設計Python程式的地方,不知道同學們是否已經眼花撩亂了呢?沒關係,現在老師幫大家總結一下,不管使用哪一個方式來執行程式,就只有兩種型式,

  • Shell方式:就是寫一行之後按下Enter按鈕,該行程式立即被執行。

  • 編輯器方式:在寫完所有的程式之後,還要按下「執行」按鈕,或是存檔之後再以「python yourcode.py」的方式執行。

第一種方式適合用來做簡單的測試,也就是你有一個想法不知道這樣做的結果是不是和你想的一樣,那就使用Shell來執行看看。在Windows的命令提示字元(Anaconda Prompt)環境下或是MacOS的終端機模式下,執行python或是ipython,均可立即進入Python Shell來執行程式指令。

第二種方式則是我們想要設計比較多行程式的方法。同學們可以先使用repl.it線上Python編輯器進行練習,或是在自己的電腦中安裝好了Anaconda之後,在於命令提示字元(Anaconda Prompt)或是MacOS的終端機中執行jupyter notebook,進入Jupyter Notebook中練習即可。

程式基本元素

程式簡單地說,就是:

把拿到的資料,經過運算及處理之後,再把結果輸出

所以,程式本身就是一連串要電腦去做事情(針對資料)的命令,把它們寫成一個腳本(Script),讓電腦逐行去執行。以下就是一個標準的Python程式:

message1 = "Hello!"
name = " Richard, " 
message2 = "how are you?"
message = message1 + name + message2
print(message)

如你所料,它的輸出結果是:

Hello! Richard, how are you?

在這個程式是,我們把要打招呼的文字資料分別放在message1、name、message2等3個變數中,然後再把這3個變數中的資料取出,串接在一起之後再放到message變數中,在第5行的時候把它輸出到螢幕上。

再來一個之前我們說明過的成績計算程式:

chi = 100
eng = 80
math = 60
total = chi + eng + math
average = total / 3
print(total, average)

在這個程式中,我們先使用3個變數,分別是chi, eng, math來記錄國文、英文、數學的三科成績。接著,把3個變數的內容拿出來,加總之後用total這個變數把它儲存在記憶體中,此外,再把total的內容取出,除以3之後再把結果放在average這個變數中。當然,和前面的程式一樣,在第6行的地方使用print這個指令把total和average這兩個變數的內容列印在螢幕上。以下是程式的執行結果:

240 80.0

變數以及型態

從上面這兩個簡單的程式來看,同學們應該可以知道,「變數」在處理資料上是非常重要的元素,它可以用來儲存我們要處理的資料,也可以用來儲存處理之後的資料,等到資料都處理完畢之後,可以隨時取出使用。

其實,變數就是在電腦記憶體裡面的一個位置空間,早期的電腦是以記憶體的位置編號(如:00A0:FFEC這樣子的型式)來表示,但是這些數字對人來說沒有意義,所以在程式語言中才會以一些英文字元、數字元以及一些符號來代替某些位置,以方便我們在程式中使用。

有了這樣的機制,在設計的程式中就可以自由地命名(沒錯,你可以取任何合法合理的名字),用來儲存程式執行過程中需要使用到的資料。但是,變數命名時要有意義,看程式的人才能夠知道這個程式是在做什麼的,例如,上面的成績計算程式我們也可以寫成以下這個樣子:

a = 100
b = 80
c = 60
d = a + b + c
e = d / 3
print(d, e)

這樣的程式仍可以得到一樣的執行結果。但是,乍看程式,你會知道這個程式主要的目的是在做什麼嗎?

命名的建議

所以,一個好的程式在為變數命名時要有一個好的習慣。最基本的原則是有意義的名字,長一點沒關係,可以善加利用大小寫或是這個程式語言中提供的一些可以區隔文字的特殊符號。

沒錯,在大部份的程式語言中,大小寫不同,就算是不同的變數。例如:abc, ABC, aBc, Abc這些都是不同的變數。儘管如此,除非你有非常充足的理由,不然就不要在你的程式中真的同時使用這樣的變數。

再舉之前計算成績的程式例,如果我們想要更強調計算的是成績,可以改為以下這個樣子:

score_chinese = 100
score_english = 80
score_mathematics = 60
score_total = score_chinese + score_english + score_mathematics
score_average = score_total / 3
print(score_total, score_average)

Python語言可以在變數的名稱中使用底線符號

這樣也可以得到一樣的結果,而且任何人一看到這個程式,就很明顯地可以知道它的目的是用來計算國文、英文、數學這三個科目的總分以及平均成績。

有些不喜歡符號的人,會喜歡使用大小寫來區分在同一個變數名稱中的兩個英文字,如下:

scoreChinese = 100
scoreEnglish = 80
scoreMathematics = 60
scoreTotal = scoreChinese + scoreEnglish + scoreMathematics
scoreAverage = scoreTotal / 3
print(scoreTotal, scoreAverage)

上述兩種命名習慣都可以達成一樣的效果,端看同學們自己的喜好,或是你的同公司、團隊之程式設計人員的規定。一般來說,當你要編寫大型的程式時,不只是變數的命名原則,甚至是要行和行之間的空行數、編寫程式註解的格式等等都有非常謹的規定,這是要留意的地方。

不過,如果同學們自行輸入這一段程式的話一定會覺得,把變數名稱設計得那麼長不是會非常麻煩,經常會有拼寫錯誤的情形嗎?沒錯,而這就是好的程式碼編輯器(如Sublime Text)的功能,它們會輔助你輸入之前曾經輸入過的任何名詞,以避免你不小心因為拼錯字而發生變數名稱不一致的情形而導致程式執行錯誤。

Python的程式有一個共通的編寫規範可以參考:

變數的型態

在前面的兩個程式中同學們應該有發現,有時候我們的變數中會存放文字內容,而有時候會存放數字內容。其實同學們應該有所瞭解,既然之前有說過變數是記憶體中的一些位置,但是每一個變數裡面要放的內容不一定,以上面的程式為例,有可能是放文字「Hello」,也有可能是放成績「80」,不同的內容要佔用的位置自然也是不一樣,因此,在程式語言中就要有一些機制可以讓電腦面對這個情況。

有一些程式語言(例如 C或是Java)要求使用者在使用變數之前要先宣告變數名稱以及該變數的型態(要存放的資料型式),如此變數在使用之前就可以知道要準備多大的記憶體空間,程式在執行上就會比較有效率。

另外一些程式語言(如Python以及Scratch)則是利用比較彈性的機制,不需要事先宣告變數,而是在使用的時候,依照當時設定值的內容來決定適用於哪一種型態。此種方式對於程式設計師來說較有彈性,但是在程式的執行效能來說就比較不好。如上面程式中的例子,我們在設定message1="Hello"時,message1這個變數就被設定為字串型態,而chinese=100時,就會把chinese這個變數設定為整數型態。在Python中,一旦變數的型態被設定了之後,在應用上就要以該型態的特性去操作它,才不致於發生錯誤。我們可以使用type指令去查詢某一個變數的型態,以下是在Shell中的操作過程:

heaohuangde-MacBook-Air:~ minhuang$ python 
Python 3.6.5 |Anaconda, Inc.| (default, Apr 26 2018, 08:42:37) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> chi = 100
>>> type(chi)
<class 'int'>
>>> message1 = "Hello"
>>> type(message1)
<class 'str'>
>>> print(chi)
100
>>> print(chi+message1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> print(chi+str(message1))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'int' and 'str'
>>> print(str(chi)+message1)
100Hello

在上述的操作過程中,在第6行以type(chi)檢查chi變數的型態,是int(也就是整數型態),而在第9行以type(message1)檢查message1變數,得到的是str(也就是字串型態)。接著,我們試著在第13行把兩個變數相加,得到的是一大串的錯誤訊息,在第17行的時候也是一樣。但是,在第21行時,我們把chi以str(chi)轉換成字串,再加上message1,結果就正常了,因為透過轉換之後,chi也變成了字串,兩個變數的內容自然就能夠串接在一起了。

對於初學者來說,最常用的基本資料型態如下:

int整數型態

不具小數點的正負號整數數值。

str字串型態

所有文字字元的組合,以成對的雙引號或是單引號來包含的內容。如果需要使用的文字內容超過一行,也可以使用三引號的方式來文置,以下是一些字串的例子:

str1 = "Hello"
str2 = 'Hello"
str3 = "That's a book"
str4 = """
this is line 1
this is line 2
"""

float浮點數型態

會使用到小數點的數值我們都把它們稱為是浮點數,只不過有精確度的差別,但是對於初學者來說,先不用去管這些。

基本輸入與輸出

在前面的程式例中,我們所有計算的內容都是寫在程式中的,如果需要讓使用者在執行程式的時候才輸入資料的話,就要使用一個叫做input的函數,如下所示的程式例:

name = input("Please enter your name:")
print ("Hello", name)

以下則是當我們輸入Richard時的輸出結果:

Please enter your name:Richard 
Hello Richard 

如果我們想要讓內容更加地生動一些,也可以把輸出的地方加上一個叫做format的函數:

name = input("Please enter your name:")
print ("Hello {}, how are you?".format(name))

format函數中的參數,會依序填到前面字串中的大括號位置。

要特別注意的是,format函數是直接以「.」串列在字串的後方,中間沒有任何空格。

同樣輸入Richard,得到的輸出結果如下:

Please enter your name:Richard 
Hello Richard , how are you?

在成績計算的例子中,如下所示的程式可以讓使用者輸入三科成績來做計算:

chi = int(input("國文成績:"))
eng = int(input("英文成績:"))
mat = int(input("數學成績:"))
total = chi + eng + mat 
average = total / 3
print("這個同學的總分是:{}分,平均是{}分。".format(total, average))

執行的結果如下:

國文成績:80
英文成績:60
數學成績:70
這個同學的總分是:210分,平均是70.0分。

留意之前關於變數型態的說明。input函數傳回值預設是字串型態,但是我們想要的是數值型態,因此就需要使用int函數把傳入的值變成數值之後再放在chi, eng, mat等變數中。

如果使用者在輸入的時候沒有內容或是輸入的不是數值,程式就會顯示錯誤並中斷執行。錯誤訊息可能非常長,如下所示(以下只是一部份訊息內容而已):

在這個例子中,我們善用了format插入字串文字的能力,讓輸出的結果更像是一句話,這個函數在輸出資料的時候非常好用,它是一個格式化輸出的函數,例如需要在輸出有小數點的數值時如果要指令小數點的位置,也可以在大括號內加上幾個簡單的格式指令,如下所示:

print("這個同學的總分是:{}分,平均是{:.2f}分。".format(total, average))

那麼在輸出的時候,平均數的地方就會以小數點以下2位的方式來顯示結果:

國文成績:90
英文成績:95
數學成績:53
這個同學的總分是:238分,平均是79.33分。

為程式加上註解

程式如果只有少少的幾行,那當然只要有良好的變數命名習慣和排版,任何人看你的程式就大約可以理解這個程式是做什麼用的。但是當程式碼變多時就沒有那麼美好了。此時,為程式加上一些「註解」就是非常好的方法,它是為程式碼加上說明的一種方法。

Python程式語言使用「#」來當做是註解用的符號。在程式中任何一個地方只要出現了「#」,則緊接在其後的任何文字、符號、數字、字元通通不會被翻譯及執行,全部會以原來的樣子呈現。因此,我們就可以在註解符號的後面自由地加上說明文字,如下所示:

# 程式作者:何敏煌
# 程式名稱:成績計算範例
# 日期:2018-10-5

# 首先,輸入3個科目的成績
chi = int(input("國文成績:"))
eng = int(input("英文成績:"))
mat = int(input("數學成績:"))
total = chi + eng + mat  # 計算總分 
average = total / 3      # 計算平均

#最後,輸出計算的結果
print("這個同學的總分是:{}分,平均是{:.2f}分。".format(total, average))

如上面的程式例子,在程式適當的地方加上一些說明,不會影響到程式內容的執行,卻加上了程式的可讀性,日後需要再回來看這個程式的時候,也就比較好理解了。

「#」符號的註解是屬於單行的,如上述的程式例,在一開始的時候有三行連續的註解,有時候我們會以三連引號字串的型式來呈現,如下所示:

'''
程式作者:何敏煌
程式名稱:成績計算範例
日期:2018-10-5
'''

# 首先,輸入3個科目的成績
chi = int(input("國文成績:"))
eng = int(input("英文成績:"))
mat = int(input("數學成績:"))
total = chi + eng + mat  # 計算總分 
average = total / 3      # 計算平均

#最後,輸出計算的結果
print("這個同學的總分是:{}分,平均是{:.2f}分。".format(total, average))

此種使用方式在註解資訊很多的時候就非常好用。

三連引號字串除了連續三個單引號之外,使用連續三個雙引號也可以。

有時候你會在程式碼一開始的時候看到 # coding=utf-8,或是# -*- coding:utf-8 -*-,那是用來指定檔案編碼方式的啟始設定。如果同學們在程式中使用到中文字在執行的時候出現編碼的錯誤訊息,通常把這一段文字編碼設定加上去就好了。

有時候在一些範例程式的第一行也會看到 #! /usr/bin/python3 ,那是Linux和MacOS的規範,可以用來指令此程式要被系統上的哪一支程式翻譯執行,如果同學們使用的是Windows,則這一行設定可以拿掉。

程式碼區塊與縮排

在前面的幾支程式中,我們平鋪直敘地編寫程式,讓每一行指令順著從第一行一路執行到最後一行之後結束,而且使用的指令敘述都非常地簡單。可是,當我們有一些情況要面對時,就需要有程式碼區塊的概念,也就是有些指令行是一起被執行或是不執行的。以下面這個例子來看:

x = int(input("請輸入通關密語:"))
if x == 7:
    print("你真幸運,答對了!")
    print("接著請前往下一關。")
else:
    print("你猜錯了!")
    print("~GAME OVER~")

此程式在使用者輸入7的時候,執行結果如下:

請輸入通關密語:7
你真幸運,答對了!
接著請前往下一關。

當使用者輸入的內容不是7的時候,則執行結果如下:

請輸入通關密語:8
你猜錯了!
~GAME OVER~

這是一個很典型的,依據使用者的輸入決定要執行哪一些程式碼的例子。在程式中,一開始讓使用者輸入一個數字,然後把使用者輸入的內容放到x這個變數。

第2行檢查x是否等於7,如果是的話,就執行第3行和第4行,如果不是的話,就執行第6行和第7行。

在這個程式中,第2行到第7行是一個完整的if/else決策指令敘述。在此敘述中,中間第3行和第4行屬於同一個區塊(假設我們把它稱為A區塊),第6行和第7行則是屬於另外一個程式碼區塊(在此假設把它稱為B區塊)。

if敘述的標準用法就是:

if 條件:
    A  # 條件成立要執行的區塊
else:
    B  # 條件不成立時要執行的區塊

要特別注意的是,同一個區塊的程式碼是以是否位於同一階層的縮排來決定。再來看看以下的程式例:

x = int(input("請輸入通關密語:"))
if x == 7:
    print("你真幸運,答對了!")
    print("接著請前往下一關。")
else:
    print("你猜錯了!")
print("~GAME OVER~")

同學們有發現此程式和前一個程式的差別了嗎?

答案就在最後一行(第7行),在這個程式中,第7行沒有縮排,所以它的位階是和if指令同層的,也就是說它不再屬於if指令了,因此,不管if指令的執行結果為何,最終第7行都會被執行到,那個GAME OVER訊息一定都會被顯示出來,同學們可以自行試試喔。

縮排的方式可以使用空格、定位鍵的方式,如果使用空格的話,要空2格或4格則由程式設計師決定,不過,不管使用何種方式,整個程式使用的方式要一致,不然會出現類似下面這樣的錯誤訊息:

IndentationError: expected an indented block

Last updated