3. 一個非正式的 Python 簡介¶
在下面的例子中,輸入與輸出的區別在於有無提示字元(prompt,>>> 和 ...):如果要重做範例,你必須在提示字元出現的時候,輸入提示字元後方的所有內容;那些非提示字元開始的文字行是直譯器的輸出。注意到在範例中,若出現單行只有次提示字元時,代表該行你必須直接換行;這被使用在多行指令結束輸入時。
你可以使用 "Copy" 按鈕(當游標移至程式碼範例上方或點選程式碼範例時,它會出現在右上角),這會去除提示字元並略過輸出,讓你可以複製貼上輸入行到你的直譯器。
在本手冊中的許多範例中,即便他們為互動式地輸入,仍然包含註解。Python 中的註解 (comments) 由 hash 字元 # 開始一直到該行結束。註解可以從該行之首、空白後、或程式碼之後開始,但不會出現在字串文本 (string literal) 之中。hash 字元在字串文本之中時仍視為一 hash 字元。因為註解只是用來說明程式而不會被 Python 解讀,在練習範例時不一定要輸入。
一些範例如下:
# 這是第一個註解
spam = 1 # 這是第二個註解
# ... 現在是第三個!
text = "# 這不是註解,因為它在引號內。"
3.1. 把 Python 當作計算機使用¶
讓我們來試試一些簡單的 Python 指令。啟動直譯器並等待第一個主提示字元 >>> 出現。(應該不會等太久)
3.1.1. 數字 (Number)¶
直譯器如同一台簡單的計算機:你可以輸入一個 expression(運算式),它會寫出該式的值。Expression 的語法可以使用:運算子 +、-、* 和 / 可以用來執行運算;括號 () 可以用來分群。例如:
>>> 2 + 2
4
>>> 50 - 5*6
20
>>> (50 - 5*6) / 4
5.0
>>> 8 / 5 # 除法總是回傳浮點數
1.6
整數數字(即 2、4、20)為 int 型別,數字有小數點部份的(即 5.0、1.6)為 float 型別。我們將在之後的教學中看到更多數字相關的型別。
除法 (/) 永遠回傳一個 float。如果要做 floor division 並拿到整數的結果,你可以使用 // 運算子;計算餘數可以使用 %:
>>> 17 / 3 # 傳統除法回傳浮點數
5.666666666666667
>>>
>>> 17 // 3 # 下取整除法捨棄小數部分
5
>>> 17 % 3 # % 運算子回傳除法的餘數
2
>>> 5 * 3 + 2 # 下取整商 * 除數 + 餘數
17
在 Python 中,計算冪次 (powers) 可以使用 ** 運算子 [1]:
>>> 5 ** 2 # 5 的平方
25
>>> 2 ** 7 # 2 的 7 次方
128
等於符號 (=) 可以用於為變數賦值。賦值完之後,在下個指示字元前並不會顯示任何結果:
>>> width = 20
>>> height = 5 * 9
>>> width * height
900
如果一個變數未被「定義 (defined)」(即變數未被賦值),試著使用它時會出現一個錯誤:
>>> n # 嘗試存取未定義的變數
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'n' is not defined
浮點數的運算有完善的支援,運算子 (operator) 遇上混合的運算元 (operand) 時會把整數的運算元轉換為浮點數:
>>> 4 * 3.75 - 1
14.0
在互動式模式中,最後一個印出的運算式的結果會被指派至變數 _ 中。這表示當你把 Python 當作桌上計算機使用者,要接續計算變得容易許多:
>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> round(_, 2)
113.06
這個變數應該被使用者視為只能讀取。不應該明確地為它賦值 --- 你可以創一個獨立但名稱相同的本地變數來覆蓋掉預設變數和它的神奇行為。
除了 int 和 float,Python 還支援了其他的數字型別,包含 Decimal 和 Fraction。Python 亦內建支援複數 (complex numbers),並使用 j 和 J 後綴來指定虛數的部份(即 3+5j)。
3.1.2. 文字¶
Python 可以操作文本(由 str 型別表示,即所謂的「字串 (strings)」)和數字。這包括字元 "!"、單詞 "rabbit"、名稱 "Paris"、句子 "Got your back." 等等。"Yay! :)"。它們可以用單引號 ('...') 或雙引號 ("...") 括起來,會具有相同的結果 [2]。
>>> 'spam eggs' # 單引號
'spam eggs'
>>> "Paris rabbit got your back :)! Yay!" # 雙引號
'Paris rabbit got your back :)! Yay!'
>>> '1975' # 以引號包含的數字和數值也是字串
'1975'
要引用引文,我們需要在其前面加上 \ 來「跳脫」它。或者我們也可以使用其他種類的引號:
>>> 'doesn\'t' # 用 \' 來跳脫單引號...
"doesn't"
>>> "doesn't" # ...或改用雙引號
"doesn't"
>>> '"Yes," they said.'
'"Yes," they said.'
>>> "\"Yes,\" they said."
'"Yes," they said.'
>>> '"Isn\'t," they said.'
'"Isn\'t," they said.'
在 Python shell 中,字串定義和輸出字串可能看起來不同。print() 函式透過省略引號並印出跳脫字元和特殊字元來生成更具可讀性的輸出:
>>> s = 'First line.\nSecond line.' # \n 表示換行
>>> s # 沒有 print(),特殊字元會包含在字串中
'First line.\nSecond line.'
>>> print(s) # 有 print(),特殊字元會被直譯,所以 \n 會產生新的一行
First line.
Second line.
如果你不希望字元前出現 \ 就被當成特殊字元時,可以改使用 raw string,在第一個包圍引號前加上 r :
>>> print('C:\this\name') # 這裡 \t 表示 tab,\n 表示換行
C: his
ame
>>> print(r'C:\this\name') # 注意引號前的 r
C:\this\name
原始字串有一個微妙的地方:原始字串可能不會以奇數個 \ 字元結尾;請參閱常見問答集來了解更多資訊和解決方法。
字串文本可以跨越數行。其中一方式是使用三個重複引號:"""...""" 或 '''...'''。此時換行字元會被自動加入字串值中,但也可以在換行前加入 \ 來取消這個行為。在以下的例子中,最初的換行符不會被包含:
>>> print("""\
... Usage: thingy [OPTIONS]
... -h Display this usage message
... -H hostname Hostname to connect to
... """)
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
>>>
字串可以使用 + 運算子連接 (concatenate),並用 * 重複該字串的內容:
>>> # 3 次 'un',接著是 'ium'
>>> 3 * 'un' + 'ium'
'unununium'
兩個以上相鄰的字串文本(string literal,即被引號包圍的字串)會被自動連接起來:
>>> 'Py' 'thon'
'Python'
當你想要分段一個非常長的字串時,兩相鄰字串值自動連接的特性十分有用:
>>> text = ('Put several strings within parentheses '
... 'to have them joined together.')
>>> text
'Put several strings within parentheses to have them joined together.'
但這特性只限於兩相鄰的字串值間,而非兩相鄰變數或運算式:
>>> prefix = 'Py'
>>> prefix 'thon' # 無法串接變數和字串字面值
File "<stdin>", line 1
prefix 'thon'
^^^^^^
SyntaxError: invalid syntax
>>> ('un' * 3) 'ium'
File "<stdin>", line 1
('un' * 3) 'ium'
^^^^^
SyntaxError: invalid syntax
如果要連接變數們或一個變數與一個字串值,使用 +:
>>> prefix + 'thon'
'Python'
字串可以被「索引 indexed」(下標,即 subscripted),第一個字元的索引值為 0。沒有獨立表示字元的型別;一個字元就是一個大小為 1 的字串:
>>> word = 'Python'
>>> word[0] # 位置 0 的字元
'P'
>>> word[5] # 位置 5 的字元
'n'
索引值可以是負的,此時改成從右開始計數:
>>> word[-1] # 最後一個字元
'n'
>>> word[-2] # 倒數第二個字元
'o'
>>> word[-6]
'P'
注意到因為 -0 等同於 0,負的索引值由 -1 開始。
除了索引外,字串亦支援「切片 slicing」。索引用來拿到單獨的字元,而切片則可以讓你拿到一個子字串 (substring):
>>> word[0:2] # 從位置 0 (包含) 到 2 (不包含) 的字元
'Py'
>>> word[2:5] # 從位置 2 (包含) 到 5 (不包含) 的字元
'tho'
切片索引 (slice indices) 有很常用的預設值,省略起點索引值時預設為 0,而省略第二個索引值時預設整個字串被包含在 slice 中:
>>> word[:2] # 從開頭到位置 2 (不包含) 的字元
'Py'
>>> word[4:] # 從位置 4 (包含) 到結尾的字元
'on'
>>> word[-2:] # 從倒數第二個 (包含) 到結尾的字元
'on'
注意到起點永遠被包含,而結尾永遠不被包含。這確保了 s[:i] + s[i:] 永遠等於 s:
>>> word[:2] + word[2:]
'Python'
>>> word[:4] + word[4:]
'Python'
這裡有個簡單記住 slice 是如何運作的方式。想像 slice 的索引值指著字元們之間,其中第一個字元的左側邊緣由 0 計數。則 n 個字元的字串中最後一個字元的右側邊緣會有索引值 n,例如:
+---+---+---+---+---+---+
| P | y | t | h | o | n |