序章
歡迎參加 Google 的 Python 線上教學課程。這項計畫以內部提供的 Python 入門課程為基礎,如設定頁面所述,本教材涵蓋 Python 3。
如要尋找相關的 MOOC 課程,請試試 Udacity 和 Coursera 的課程 (程式設計入門 [初學者] 或 Python 入門)。最後,如果您想不觀看影片,而是尋求自修式線上學習,請試試這篇文章結尾列出的課程。這些課程都提供功能學習內容,以及可供練習的 Python 互動式解譯器。我們提到的「解譯器」是什麼?我們會在下一節說明!
語言簡介
Python 是一種動態解譯 (位元組碼編譯) 語言。原始碼中沒有變數、參數、函式或方法的型別宣告。這會讓程式碼簡短且彈性,但您會失去原始碼的編譯時間型別檢查。Python 會在執行階段追蹤所有值的型別,並標示執行時沒有意義的程式碼。
如要瞭解 Python 程式碼的運作方式,最簡單的方法就是執行 Python 解譯器,然後直接在其中輸入程式碼。如果遇到「在 list
中新增 int
會發生什麼事?」這類問題,只要在 Python 解譯器中輸入問題,就能快速找出答案,而且這可能是最佳做法。(請參閱下文,瞭解實際情況!)
$ python3 ## Run the Python interpreter Python 3.X.X (XXX, XXX XX XXXX, XX:XX:XX) [XXX] on XXX Type "help", "copyright", "credits" or "license" for more information. >>> a = 6 ## set a variable in this interpreter session >>> a ## entering an expression prints its value 6 >>> a + 2 8 >>> a = 'hi' ## 'a' can hold a string just as well >>> a 'hi' >>> len(a) ## call the len() function on a string 2 >>> a + len(a) ## try something that doesn't work Traceback (most recent call last): File "" , line 1, inTypeError: can only concatenate str (not "int") to str >>> a + str(len(a)) ## probably what you really wanted 'hi2' >>> foo ## try something else that doesn't work Traceback (most recent call last): File " " , line 1, inNameError: name 'foo' is not defined >>> ^D ## type CTRL-d to exit (CTRL-z in Windows/DOS terminal)
輸入 python 後,python 會印出兩行文字,然後顯示 >>> 提示,說明您使用的 python 版本和建構位置。只要印出的第一個項目是「Python 3.」,這些範例就應該適用於您。
如上所示,您可以輕鬆實驗變數和運算子。此外,如果程式碼嘗試讀取尚未指派值的變數,解譯器會擲回 (在 Python 術語中稱為「引發」) 執行階段錯誤。與 C++ 和 Java 類似,Python 區分大小寫,因此「a」和「A」是不同的變數。行尾代表陳述式結尾,因此 Python 不像 C++ 和 Java,不需要在每個陳述式結尾加上半形分號。註解以「#」開頭,並延伸至行尾。
Python 原始碼
Python 來源檔案使用「.py」副檔名,稱為「模組」。使用 Python 模組 hello.py
時,最簡單的執行方式是使用殼層指令「python hello.py Alice」,這會呼叫 Python 解譯器來執行 hello.py
中的程式碼,並將指令列引數「Alice」傳遞給該程式碼。如要瞭解從指令列執行 Python 時的所有不同選項,請參閱官方文件頁面。
以下是簡單的 hello.py
程式 (請注意,程式碼區塊是使用縮排而非大括號嚴格分隔,稍後會詳細說明!):
#!/usr/bin/python3 # import modules used here -- sys is a very standard one import sys # Gather our code in a main() function def main(): print('Hello there', sys.argv[1]) # Command line args are in sys.argv[1], sys.argv[2] ... # sys.argv[0] is the script name itself and can be ignored # Standard boilerplate to call the main() function to begin # the program. if __name__ == '__main__': main()
從指令列執行這個程式的樣子如下:
$ python3 hello.py Guido Hello there Guido $ ./hello.py Alice ## without needing 'python3' first (Unix) Hello there Alice
匯入、指令列引數和 len()
Python 檔案或「模組」中最外層的陳述式會執行一次性設定,這些陳述式會在模組首次匯入某處時從上到下執行,設定模組的變數和函式。Python 模組可以直接執行 (如上述 python3 hello.py Bob
),也可以匯入並由其他模組使用。直接執行 Python 檔案時,特殊變數「__name__」會設為「__main__」。因此,當模組直接執行時,常見的做法是使用上述的樣板 if __name__ ==...
呼叫 main() 函式,但當模組由其他模組匯入時,則不會呼叫。
在標準 Python 程式中,清單 sys.argv
會以標準方式包含指令列引數,其中 sys.argv[0] 是程式本身,sys.argv[1] 是第一個引數,依此類推。如果您知道 argv
或引數數量,可以像上方互動式解譯器程式碼要求字串長度時一樣,直接使用 len(sys.argv)
向 Python 要求這個值。一般來說,len()
可以告訴您字串的長度、清單和元組 (另一種類似陣列的資料結構) 中的元素數量,以及字典中的鍵/值組合數量。
使用者定義函式
Python 中的函式定義如下:
# Defines a "repeat" function that takes 2 arguments. def repeat(s, exclaim): """ Returns the string 's' repeated 3 times. If exclaim is true, add exclamation marks. """ result = s + s + s # can also use "s * 3" which is faster (Why?) if exclaim: result = result + '!!!' return result
請注意,構成函式或 if 陳述式的行會分組,因為這些行具有相同的縮排層級。我們也介紹了兩種重複字串的方式,一種是使用較容易上手的 + 運算子,另一種是使用 *,因為這是 Python 的「重複」運算子,也就是說 '-' * 10
會產生 '----------'
,這是建立螢幕「線條」的簡潔方式。在程式碼註解中,我們暗示 * 的運作速度比 + 快,原因在於 * 會計算結果物件的大小一次,而 + 每次呼叫時都會進行計算。「+」和「*」都稱為「多載」運算子,因為它們對數字和字串 (以及其他資料型別) 的意義不同。
def
關鍵字會定義函式,並將參數放在括號內,程式碼則會縮排。函式的第一行可以是說明函式用途的說明文件字串 (「docstring」)。如上例所示,docstring 可以是單行,也可以是多行說明。(沒錯,這是「三引號」,Python 獨有的功能!) 函式中定義的變數是該函式的本機變數,因此上述函式中的「result」與另一個函式中的「result」變數不同。return
陳述式可以接受引數,在這種情況下,該引數就是傳回給呼叫端的結果。
以下程式碼會呼叫上述 repeat() 函式,並列印傳回的內容:
def main(): print(repeat('Yay', False)) ## YayYayYay print(repeat('Woo Hoo', True)) ## Woo HooWoo HooWoo Hoo!!!
在執行階段,函式必須先透過執行「def」定義,才能呼叫。通常會在檔案底部定義 main() 函式,並在上方呼叫函式。
縮排
Python 的一項特殊功能是,程式碼的空白字元縮排會影響其意義。構成函式的陳述式等邏輯區塊,都應與上層函式或「if」等項目的縮排相同。如果群組中的某一行縮排不同,系統就會標示為語法錯誤。
Python 使用空白字元的方式一開始有點奇怪,但其實很合理,我很快就習慣了。請避免使用 TAB 鍵,因為這會大幅增加縮排配置的複雜度 (更別說 TAB 鍵在不同平台上的意義可能不同)。將編輯器設為插入空格,而非 Python 程式碼的 TAB 鍵。
初學者常問的問題是「應該縮排幾個空格?」根據官方 Python 樣式指南 (PEP 8),您應縮排 4 個空格。(有趣的是,Google 內部樣式指南規定縮排 2 個空格!)
在執行階段檢查程式碼
Python 在編譯時幾乎不會進行檢查,而是將每行程式碼的類型、名稱等檢查作業延後到該行執行時。假設上述 main() 呼叫 repeat(),如下所示:
def main(): if name == 'Guido': print(repeeeet(name) + '!!!') else: print(repeat(name))
if 陳述式含有明顯錯誤,repeat() 函式意外輸入為 repeeeet()。有趣的是,只要執行階段的名稱不是「Guido」,這段 Python 程式碼就能順利編譯及執行。只有在執行作業實際嘗試執行 repeeeet() 時,才會發現沒有這類函式並引發錯誤。這個程式碼片段中還有第二個錯誤;name 在與「Guido」比較之前,並未獲派值。如果您嘗試評估未指派的變數,Python 會引發「NameError」。這些範例說明首次執行 Python 程式時,您看到的第一批錯誤可能是一些簡單的錯字或未初始化的變數。在這種情況下,Java 等語言的詳細型別系統就具有優勢,因為這類系統可以在編譯時偵測到這類錯誤 (但當然,您必須維護所有型別資訊,這是一種取捨)。
Python 3 導入了型別提示。
型別提示可讓您指出函式中每個引數的型別,以及函式傳回的物件型別。舉例來說,在註解函式 def is_positive(n: int) -> bool:
中,引數 n
是 int
,傳回值是 bool
。我們稍後會說明這些型別的意義。不過,型別提示完全是選用功能。
您會發現越來越多程式碼採用型別提示,因為使用型別提示後,cider-v 和 VS.code 等編輯器就能執行檢查,確認函式是否以正確的引數型別呼叫。甚至能在您編輯程式碼時,建議及驗證引數。本教學課程不會介紹型別提示,但我們希望您瞭解這些提示,以便在聽說或看到這些提示時有所認識。
變數名稱
由於 Python 變數在原始碼中沒有任何類型,因此為變數命名時,請盡量使用有意義的名稱,提醒自己變數的用途。因此,如果是單一名稱,請使用「name」;如果是名稱清單,請使用「names」;如果是元組清單,請使用「tuples」。 許多基本的 Python 錯誤都是因為忘記每個變數中的值類型所致,因此請使用變數名稱 (您真正擁有的所有名稱),協助釐清狀況。
就實際命名而言,有些語言偏好使用底線分隔「多個單字」組成的變數名稱,但其他語言則偏好使用駝峰式大小寫。一般來說,Python 偏好使用底線方法,但如果整合到已使用該樣式的現有 Python 程式碼中,則會引導開發人員延後使用 camelCasing。可讀性分數。詳情請參閱 PEP 8 中的命名慣例章節。
如您所料,「if」和「while」等關鍵字無法做為變數名稱,否則會發生語法錯誤。不過,請注意不要使用內建項目做為變數名稱。舉例來說,雖然「str」、「list」和「print」看似是不錯的名稱,但您會覆寫這些系統變數。內建函式並非關鍵字,因此新 Python 開發人員可能會不慎使用。
模組及其命名空間的詳細資訊
假設您有一個「binky.py」模組,其中包含「def foo()」。該 foo 函式的完整格式名稱為「binky.foo」。這樣一來,各種 Python 模組就能隨意命名函式和變數,變數名稱也不會衝突 (module1.foo 與 module2.foo 不同)。在 Python 詞彙中,我們會說 binky、module1 和 module2 各有自己的「命名空間」,也就是變數名稱到物件的繫結。
舉例來說,我們有標準的「sys」模組,其中包含一些標準系統設施,例如 argv 清單和 exit() 函式。使用「import sys」陳述式後,您就可以存取 sys 模組中的定義,並透過完整名稱 (例如 sys.exit()) 提供這些定義。(沒錯,「sys」也有命名空間!)
import sys # Now can refer to sys.xxx facilities sys.exit(0)
還有另一個匯入表單,看起來像這樣:「from sys import argv, exit」。這樣一來,您就能使用簡短名稱存取 argv 和 exit();不過,我們建議使用完整名稱的原始形式,因為這樣比較容易判斷函式或屬性來自何處。
Python 解譯器標準安裝套件中包含許多模組和套件,因此您不必採取任何額外行動即可使用。這些統稱為「Python 標準程式庫」。常用的模組/套件包括:
- sys - access to exit(), argv, stdin, stdout, ...
- re - 規則運算式
- os - 作業系統介面、檔案系統
如要查看所有標準程式庫模組和套件的說明文件,請前往 http://docs.python.org/library。
線上說明、help()
和 dir()
您可以透過多種方式取得 Python 相關協助。
- 從「python」一詞開始進行 Google 搜尋,例如「python list」或「python string lowercase」。通常第一個結果就是答案。由於某些原因,這項技術似乎更適合 Python,而非其他語言。
- 官方 Python 文件網站 (docs.python.org) 提供高品質文件。不過,我通常覺得用幾個字詞進行 Google 搜尋比較快。
- 此外,我們也提供官方 Tutor 郵寄清單,專為 Python 和/或程式設計新手設計!
- 許多問題 (和解答) 都可以在 StackOverflow 和 Quora 上找到。
- 使用 help() 和 dir() 函式 (如下所示)。
在 Python 解譯器中,help() 函式會提取各種模組、函式和方法的說明文件字串。這些文件字串類似於 Java 的 Javadoc。dir() 函式會告訴您物件的屬性。以下是從解譯器呼叫 help() 和 dir() 的幾種方式:
help(len)
:內建len()
函式的說明字串;請注意,這是「len」而非「len()」,後者是函式的呼叫,我們不希望這樣做help(sys)
:sys
模組的說明字串 (必須先執行import sys
)dir(sys)
-dir()
類似於help()
,但只會提供定義符號或「屬性」的快速清單help(sys.exit)
:sys
模組中exit()
函式的說明字串help('xyz'.split)
:字串物件的split()
方法說明字串。您可以呼叫help()
,並傳入該物件本身或該物件的範例,以及其屬性。舉例來說,呼叫help('xyz'.split)
等於呼叫help(str.split)
。help(list)
:list
物件的說明字串dir(list)
:顯示list
物件屬性,包括其方法help(list.append)
:list
物件的append()
方法說明字串