Python 簡介

序章

歡迎參加 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, 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」是不同的變數。行尾代表陳述式結尾,因此 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: 中,引數 nint,傳回值是 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 和/或程式設計新手設計!
  • 許多問題 (和解答) 都可以在 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() 方法說明字串