Python 簡介

序章

歡迎使用 Google 的 Python 線上教學課程。本課程以內部提供的 Python 入門課程為基礎。如設定頁面所述,本資料涵蓋 Python 3。

如果您想找相關的網路開放式課程,不妨試試 Udacity 和 Coursera 的課程 (程式設計入門 [初學者] 或 Python 入門)。最後,如果您想不看影片,以自學方式在線上學習,不妨試試這篇文章結尾列出的資源。每個資源都提供學習內容,以及可供練習的 Python 互動式轉譯器。我們提到的「口譯員」是什麼?請參閱下一節的說明。

語言簡介

Python 是動態解譯 (以位元組編譯) 語言。原始碼中沒有變數、參數、函式或方法的型別宣告。這可讓程式碼變得簡短且靈活,但您將無法對原始碼進行編譯時間型別檢查。Python 會在執行階段追蹤所有值的類型,並標示在執行期間不合理的程式碼。

如要瞭解 Python 程式碼的運作方式,請執行 Python 解譯器,然後直接在其中輸入程式碼。如果您有類似「如果我將 int 新增至 list,會發生什麼情況?」的問題,只要在 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, in 
TypeError: 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, in 
NameError: 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」是不同的變數。行尾標示陳述式的結尾,因此與 C++ 和 Java 不同,Python 不需要在每個陳述式結尾加上分號。註解以 '#' 開頭,並延伸至該行的結尾。

Python 原始碼

Python 來源檔案使用「.py」擴充功能,並稱為「modules」。透過 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] 是程式本身,依此類推。如果您知道 argc 或引數數量,只要使用 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 陳述式所組成的行會以相同的縮排層級分組。我們也介紹了 2 種重複字串的方式,分別是使用更友善的 + 運算子,以及 Python 的「重複」運算子,也就是 *,這意味著 '-' * 10 會產生 '----------',這是在螢幕上建立「行」的簡單方法。在程式碼註解中,我們提示 * 運作的速度比 + 快,原因在於 * 計算結果物件的大小一次,若帶有 +,則計算會在每次呼叫 + 時計算。+ 和 * 都稱為「超載」運算子,因為數字與字串 (以及其他資料類型) 的含義不同。

def 關鍵字會定義函式,並在函式內使用括號和縮排的程式碼定義參數。函式的首行可以是說明函式用途的文檔字串 (「docstring」)。docstring 可以是單行或多行說明,如上例所示。(沒錯,這些是「三重引號」,是 Python 獨有的功能!)在函式中定義的變數是該函式的本機變數,因此上述函式中的「結果」與其他函式中的「結果」變數是分開的。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 在不同平台上的意義可能不同)。設定讓編輯器插入空格,而非以 TAB 的形式插入 Python 程式碼。

初學者常問的問題是:「我應該縮排幾個空格?」根據 官方 Python 樣式指南 (PEP 8),您應縮排 4 個空格。(有趣的事實:Google 內部風格指南規定縮排 2 個空格!)

在執行階段檢查的程式碼

Python 在編譯期間幾乎沒有檢查,幾乎所有類型、名稱等等都會去檢查每一行,直到該行執行為止。假設上述 main() 呼叫 repeat() 的情況如下:

def main():
    if name == 'Guido':
        print(repeeeet(name) + '!!!')
    else:
        print(repeat(name))

if 陳述式含有明顯錯誤,其中 repeat() 函式不小心輸入為 repeeeet()。在 Python 中,有趣的是,只要執行階段中的名稱不是「Guido」,這個程式碼就會正常編譯及執行。只有在執行程式實際嘗試執行 repeeeet() 時,才會發現沒有此函式,並發出錯誤。這個程式碼片段還有第二個錯誤。在與「Guido」進行比較之前,系統並未為 name 指派值。如果您嘗試評估未指派的變數,Python 會引發「NameError」。以下是一些範例,說明首次執行 Python 程式時,您會看到的部分初始錯誤,這些錯誤可能是簡單的打字錯誤,或是未初始化的變數。在這個領域,使用較冗長型別系統的語言 (例如 Java) 就佔有優勢,因為這些語言可以在編譯時偵測到這類錯誤 (但當然,您必須維護所有這類型別資訊,這是一種取捨)。

Python 3 引入了型別提示。您可以使用類型提示,指出函式中每個引數的類型,以及函式傳回物件的類型。舉例來說,在附註函式 def is_positive(n: int) -> bool: 中,引數 nint,傳回值則是 bool。我們稍後會說明這些類型的意義。不過,類型提示完全是選用的。您會發現越來越多的程式碼採用類型提示,因為如果您使用類型提示,某些編輯器 (例如 cider-v 和 VS.code) 就能執行檢查,驗證函式是否以正確的引數類型呼叫。在您編輯程式碼時,這些函式甚至可以建議和驗證引數。本教學課程不會介紹型別提示,但我們希望您瞭解這項功能,以免在實際使用時感到困惑。

變數名稱

由於 Python 變數在原始碼中沒有任何型別,因此為變數命名有助於提醒您目前的情況。因此,如果是單一名稱,請使用「name」;如果是名稱清單,請使用「names」;如果是元組清單,請使用「tuples」。 忘記每個變數中的值類型會造成許多基本 Python 錯誤,因此請使用變數名稱 (您實際上只需要) 讓事情保持簡單明瞭。

就實際命名而言,某些語言會在變數名稱中使用底線分隔符號,以便表示「多個字詞」,但其他語言則偏好駝峰式命名法。一般來說,Python 偏好使用底線方法,但如果要整合至已使用該樣式的現有 Python 程式碼,則會引導開發人員改用駝峰式命名法。可讀性很重要。詳情請參閱 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.exit() (是的,'sys' 也有命名空間!)

  import sys

  # Now can refer to sys.xxx facilities
  sys.exit(0)

還有另一種匯入形式,如下所示:「from sys import argv, exit」。這樣一來,您就能使用 argv 和 exit() 的簡寫名稱;不過,我們建議您使用原始表單,並使用完整的名稱,因為這樣一來,您就能更輕鬆地判斷函式或屬性來自何處。

有許多模組和套件隨附在 Python 解譯器的標準安裝中,因此您無需執行任何操作即可使用這些模組和套件。這些統稱為「Python 標準程式庫」。常用的模組/套件包括:

  • sys - 存取 exit()、argv、stdin、stdout 等
  • re - 規則運算式
  • os — 作業系統介面、檔案系統

如要查看所有標準程式庫模組和套件的說明文件,請前往 http://docs.python.org/library

線上說明、help()dir()

您可以透過多種方式取得 Python 相關協助。

  • 在 Google 搜尋中輸入「python」開頭的字詞,例如「python 清單」或「python 字串小寫」。第一個搜尋結果通常就是答案。這項技巧似乎在 Python 上比其他語言更有效。
  • 官方 Python 文件網站 docs.python.org 提供優質文件。無論如何,我常常在 Google 上搜尋一些字詞,想用較快的速度完成搜尋。
  • 我們也設有官方導師郵寄清單,專門提供給 Python 和/或程式設計新手!
  • 您可以在 StackOverflowQuora 上找到許多問題 (和解答)。
  • 使用 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() 方法的說明字串