# 1. Python 基礎 ## 變數 1. 名稱必須只是一個單字。 ```python >>> # 這樣不行 >>> my variable = 'Hello' >>> # 正確 >>> var = 'Hello' ``` 2. 名稱只能包含字母 (A-z)、數字 (0-9) 與底線(`_`)字元。 ```python >>> # 這樣不行 >>> %$@variable = 'Hello' >>> # 正確 >>> my_var = 'Hello' >>> # 正確 >>> my_var_2 = 'Hello' ``` 3. 名稱不能以數字開始。 ```python >>> # 這樣不行 >>> 23_var = 'hello' ``` 4. 不要使用 Python 的關鍵字或內建函數作為變數名稱。 ```python >>> # 這樣不行 >>> if = 'hello' >>> # 這樣也不好 >>> print = 'world' ``` ## 資料型別 | 資料型別 | 範例 | | ---------------------- | ----------------------------------------- | | 布林值 (Bool) | `True`, `False` | | 整數 (Integers) | `-2, -1, 0, 1, 2, 3, 4, 5` | | 浮點數 (Floating-point numbers) | `-1.25, -1.0, -0.5, 0.0, 0.5, 1.0, 1.25` | | 複數 (Complex numbers) | `2+1j`, `3-5j` | | 字串 (Strings) | `'a', 'aa', 'aaa', 'Hello!', '11 cats'` | :::info :bulb: 可使用內建函數 `type()` 來驗證賦值給變數的值的資料型別。 ::: ## 數學運算子 從**最高**到**最低**優先權: | 運算子 | 運算 | 範例 | | ------------ | ------------------------ | ------------------- | | **\*\*** | 指數運算 | `2 ** 3 = 8` | | **%** | 取餘數/模運算 | `22 % 8 = 6` | | **//** | 向下取整除法(整數除法) | `22 // 8 = 2` | | **/** | 浮點數除法(真除法) | `22 / 8 = 2.75` | | **\*** | 乘法 | `3 * 3 = 9` | | **-** | 減法 | `5 - 2 = 3` | | **+** | 加法 | `2 + 2 = 4` | | **>>, <<** | 位移運算 | `16 >> 2` | | **&, ^, \|**| 位元邏輯運算 | `1 ^ 0` | | **>, >=, ==**| 比較運算符 | `2 != 3` | | **not, and, or** | 邏輯運算子 | `(4 < 5) and (5 < 6)`| | **=, +=, \*=** | 指派運算子 | `a += 1` | :::info :bulb: 你可以使用括號來正確指定複雜運算式中運算的順序。 ::: ### 運算式範例 ```python >>> 2 + 3 * 6 # 20 >>> (2 + 3) * 6 # 30 >>> 2 ** 8 # 256 >>> 10 / 2 # 5.0 >>> -11 / 2 # -5.5 >>> 23 // 7 # 3 >>> -5.0 // 2 # -3.0 >>> 23 % 7 # 2 >>> (5 - 1) * ((7 + 1) / (3 - 1)) # 16.0 ``` ## 增強指派運算子 | 運算子 | 等價表達 | | ------------ | ---------------------- | | `var += 1` | `var = var + 1` | | `var -= 1` | `var = var - 1` | | `var *= 1` | `var = var * 1` | | `var /= 1` | `var = var / 1` | | `var %= 1` | `var = var % 1` | | `var **= 2` | `var = var ** 2` | 範例: ```python >>> greeting = 'Hello' >>> greeting += ' world!' >>> greeting # 'Hello world!' >>> number = 1 >>> number += 1 >>> number # 2 ``` ## 多重指派 ```python my_string = 'characters' my_Boolean = True # True/False my_integer = 5 my_floating_point = 26.2 my_complex = 2+1j # 注意:1 不能省略 # 上述程式碼等價於: my_string, my_Boolean, my_integer, my_floating_point, my_complex = 'characters', True, 5, 26.2, 2+1j ``` ## 字串串接與複製 ### 字串串接 ```python >>> 'Alice' + 'Bob' # 'AliceBob' ``` ### 字串複製 ```python >>> 'Alice' * 5 # 'AliceAliceAliceAliceAlice' ``` ## 註解 ### 行內註解 ```python # 這是一則註解 ``` ### 多行註解 ```python # 這是 # 一則多行註解 ``` 帶有註解的程式碼: ```python a = 1 # 初始化 ``` 也可以使用函數的文件字串(docstring)或多行字串作為註解: ```python """ 這是一個函數的文件字串 你也可以把它用作多行註解 """ ``` ## `print()` 函數 `print()` 函數會寫出它所給予參數的值。它能處理多個參數、浮點數以及字串。字串在印出時不會包含引號,而且各項之間會自動加入空格,這樣可以使格式看起來更整齊: ```python >>> print('Hello world!') # Hello world! >>> a = 1 >>> print('Hello world!', a) # Hello world! 1 >>> print('Hello,\ World') # 可使用反斜線 `\` 將敘述跨行 # Hello, World ``` ### 跳脫序列 ```python >>> print("Welcome\nto\nthe course") # Welcome # to # the course ``` ### end 參數 關鍵字參數 `end` 可用來避免印出後自動換行,或以其他字串結尾: ```python print("Welcome", end='-') print("to the course") ... # Welcome-to the course ``` ### sep 參數 關鍵字 `sep` 用來指定多個物件之間的分隔符號,預設為空白: ```python print('cats', 'dogs', 'mice', sep=',') # cats,dogs,mice ``` ## `input()` 函數 此函數從使用者那裡取得輸入,並將其轉換成字串: ```python >>> print('What is your name?') # 詢問使用者的名字 >>> my_name = input() >>> print('Hi ' + my_name) # What is your name? # Martha # Hi Martha ``` `input()` 也可以直接設置預設提示訊息而不需另外使用 `print()`: ```python >>> my_name = input('What is your name? ') # 預設提示訊息 >>> print('Hi ' + my_name) # What is your name? Martha # Hi Martha ``` ## `len()` 函數 計算字串、清單、字典等中字符的數量,並返回其整數值: ```python >>> len('hello') # 5 ``` ## `bool()`、`int()`、`float()`、`complex()` 與 `str()` 函數 這些函數允許你轉換變數的型別。例如,你可以將 `integer` 或 `float` 轉換成 `string`: ```python >>> str(29) # '29' >>> str(-3.14) # '-3.14' ``` 或者將 `string` 轉換成 `integer` 或 `float`: ```python >>> int('11') # 11 >>> float('3.14') # 3.14 ``` # 2. 流程控制 ## 比較運算子 | 運算子 | 意義 | |----------|-------------------------| | `==` | 等於 | | `!=` | 不等於 | | `<` | 小於 | | `>` | 大於 | | `<=` | 小於或等於 | | `>=` | 大於或等於 | 這些運算子會根據你給予的值計算為 `True` 或 `False`。 範例: ```python >>> 42 == 42 True >>> 40 == 42 False >>> 'hello' == 'hello' True >>> 'hello' == 'Hello' False >>> 'dog' != 'cat' True >>> 42 == 42.0 True >>> 42 == '42' False ``` ## 布林(邏輯)運算子 有三個布林運算子:`and`、`or` 和 `not`。 ### `and` 運算子的真值表: | 運算式 | 運算結果 | |----------------------|-----------| | `True and True` | `True` | | `True and False` | `False` | | `False and True` | `False` | | `False and False` | `False` | ### `or` 運算子的真值表: | 運算式 | 運算結果 | |---------------------|-----------| | `True or True` | `True` | | `True or False` | `True` | | `False or True` | `True` | | `False or False` | `False` | ### `not` 運算子的真值表: | 運算式 | 運算結果 | |-------------|-----------| | `not True` | `False` | | `not False` | `True` | ## 混合運算子 你可以混合使用布林運算子和比較運算子: ```python >>> (4 < 5) and (5 < 6) True >>> (4 < 5) and (9 < 6) False >>> (1 == 2) or (2 == 2) True ``` 另外,你也可以在一個運算式中同時使用多個布林運算子以及比較運算子: ```python >>> 2 + 2 == 4 and not 2 + 2 == 5 and 2 * 2 == 2 + 2 True ``` ## `if` 敘述 `if` 敘述會執行一個運算式,如果該運算式為 `True`,則執行以下縮排的程式碼: ```python >>> name = 'Debora' >>> if name == 'Debora': ... print('Hi, Debora') ... # Hi, Debora >>> if name != 'George': ... print('You are not George') ... # You are not George ``` `else` 敘述僅在 `if` 以及所有 `elif` 運算式計算為 `False` 時執行: ```python >>> name = 'Debora' >>> if name == 'George': ... print('Hi, George.') ... else: ... print('You are not George') ... # You are not George ``` 只有當 `if` 敘述的運算式計算為 `False` 時,`elif` 敘述才會被計算並執行: ```python >>> name = 'George' >>> if name == 'Debora': ... print('Hi Debora!') ... elif name == 'George': ... print('Hi George!') ... # Hi George! ``` `elif` 與 `else` 部分都是可選的。 ```python >>> name = 'Antony' >>> if name == 'Debora': ... print('Hi Debora!') ... elif name == 'George': ... print('Hi George!') ... else: ... print('Who are you?') ... # Who are you? ``` :::info :bulb: 請注意,Python 在 Python 3.10 中引入了 [`match`](https://learnpython.com/blog/python-match-case-statement/) 敘述,作為實作 `switch` 敘述的另一種控制敘述。 ::: ## `while` 迴圈敘述 `while` 迴圈用於在一個運算式為 `True` 的情況下重複執行程式碼: ```python >>> spam = 0 >>> while spam < 5: ... print('Hello, world.') ... spam = spam + 1 ... # Hello, world. # Hello, world. # Hello, world. # Hello, world. # Hello, world. ``` ## `break` 敘述 如果執行流程到達一個 `break` 敘述,它會立即退出 `while` 迴圈的區塊: ```python >>> while True: ... name = input('Please type your name: ') ... if name == 'your name': ... break ... >>> print('Thank you!') # Please type your name: your name # Thank you! ``` 它同樣適用於 `for` 迴圈: ```python >>> for i in range(5): ... if i == 3: ... break ... print(i) # 0 # 1 # 2 ``` ## `continue` 敘述 當程式執行到 `continue` 敘述時,會立即跳回迴圈起始處開始下一次迭代。 ```python >>> while True: ... name = input('Who are you? ') ... if name != 'Joe': ... continue ... password = input('Password? (It is a fish.): ') ... if password == 'swordfish': ... break ... >>> print('Access granted.') # Who are you? Charles # Who are you? Debora # Who are you? Joe # Password? (It is a fish.): swordfish # Access granted. ``` 它也適用於 `for` 迴圈: ```python >>> for i in range(5): ... if i == 3: ... continue ... print(i) # 0 # 1 # 2 # 4 ``` ## `for` 迴圈 `for` 迴圈會遍歷一個可迭代的物件,如 `range()`、`list`、`tuple`、`dictionary`、`set` 或 `string`: ```python >>> pets = ['Bella', 'Milo', 'Loki'] >>> for pet in pets: ... print(pet) ... # Bella # Milo # Loki ``` ## `range()` 函數 `range()` 函數會返回一個數字序列。它從 0 開始,每次遞增 1,並在指定的數字之前停止: ```python >>> for i in range(5): ... print('Will stop at 5! or 4 ?' + str(i)) ... # Will stop at 5! or 4 ?0 # Will stop at 5! or 4 ?1 # Will stop at 5! or 4 ?2 # Will stop at 5! or 4 ?3 # Will stop at 5! or 4 ?4 ``` `range()` 函數也可以修改它的預設三個引數。前兩個分別為 `start` 和 `stop` 值,第三個為 `step` 引數。間隔值表示每次迭代後變數增加的數量。 ```python # range(start, stop, step) >>> for i in range(0, 10, 2): ... print(i) ... # 0 # 2 # 4 # 6 # 8 ``` 你甚至可以使用負數作為間隔引數,使 `for` 迴圈遞減而非遞增: ```python >>> for i in range(5, -1, -1): ... print(i) ... # 5 # 4 # 3 # 2 # 1 # 0 ``` ## 使用 `sys.exit()` 結束程式 `exit()` 函式允許結束 Python 程式。 ```python >>> import sys >>> while True: ... feedback = input('Type exit to exit: ') ... if feedback == 'exit': ... print('You typed ' + feedback) ... sys.exit() ... # Type exit to exit: open # Type exit to exit: close # Type exit to exit: exit # You typed exit ``` ## [random](https://docs.python.org/3/library/random.html) 模組 ### `seed()` `seed` 方法用於初始化隨機數產生器。 ```python >>> random.seed(1) >>> random.random() # 0.13436424411240122 ``` 設定種子為一個數字,將永遠返回相同的隨機數: ```python >>> random.seed(1) >>> random.random() # 0.13436424411240122 >>> random.seed(1) >>> random.random() # 0.13436424411240122 >>> random.seed(1) >>> random.random() # 0.13436424411240122 >>> random.seed(1) >>> random.random() # 0.13436424411240122 >>> random.seed(1) >>> random.random() # 0.13436424411240122 ``` ### `randint()` ```python random.randint(start: int, stop: int) ``` 此方法返回介於給定起始與終止引數之間的隨機數: ```python >>> random.randint(1, 5) # 3 >>> random.randint(1, 5) # 2 >>> random.randint(1, 5) # 5 >>> random.randint(1, 5) # 1 >>> random.randint(1, 5) # 3 >>> random.randint(1, 5) # 1 ``` # 3. Python 函數 ## 函數參數 函數可以接受 `參數` 並回傳 `返回值`: 在以下範例中,函數 `say_hello()` 接受參數 "name" 並印出問候語: ```python >>> def say_hello(name): ... print('Hello', name) ... >>> say_hello('Carlos') # Hello Carlos >>> say_hello('Wanda') # Hello Wanda >>> say_hello('Rose') # Hello Rose ``` 上述的函數並不回傳任何值(隱式地,回傳 `None`),這樣的函數稱為 **無返回值函數 (void function)**。以下這個函數則會回傳值,因此被稱為 **有返回值的函數 (fruitful function)**: ```python >>> def my_sum(x,y): ... "Compute x + y." ... return x + y >>> my_sum(1,2) # 3 ``` ## 關鍵字參數 (Keyword Arguments) 在定義函數時,我們列出輸入的參數。這些參數被稱為位置參數(或位置引數),因為在 `def` 聲明中,參數的位置決定了每個參數的對應關係。 ```python >>> def poly(x,y): ... "Compute x + y**2." ... return x + y**2 >>> poly(1,2) # 5 >>> poly(2,1) # 3 ``` 我們可以為參數設定默認值: ```python >>> def psum(x,y,p=2): ... return x**p + y**p >>> psum(1,2) # 5 ``` 為了提高程式碼可讀性,應該盡量做到明確。我們可以使用 `關鍵字參數 (Keyword Arguments)` 來實現這一點: ```python >>> def say_hi(name, greeting): ... print(greeting, name) ... >>> # 使用位置參數 >>> say_hi('John', 'Hello') # Hello John >>> # 使用關鍵字參數 >>> say_hi(name='Anna', greeting='Hi') # Hi Anna ``` ## 返回值 (Return Values) 當使用 `def` 來創建函數時,你可以使用 `return` 來指定函數的返回值。`return` 語句由以下部分構成: - `return` 關鍵字。 - 函數應該回傳的值或表達式。 ```python >>> def sum_two_numbers(number_1, number_2): ... return number_1 + number_2 ... >>> result = sum_two_numbers(7, 8) >>> print(result) # 15 ``` :::info :bulb: 你經常會看到 `**kwargs` 用來收集不特定的關鍵字參數。`**kwargs` 必須是最右邊的參數。 ::: ## 局部範圍與全局範圍 - 全局範圍中的程式碼不能使用任何局部變數。 - 然而,局部範圍可以訪問全局變數。 - 函數的局部範圍中的程式碼不能使用其他局部範圍中的變數。 - 如果變數位於不同範圍中,可以使用相同的名稱。也就是說,`spam` 可以是局部變數,也可以是全局變數。 ```python global_variable = 'I am available everywhere' >>> def some_function(): ... print(global_variable) # 因為是全局的 ... local_variable = "only available within this function" ... print(local_variable) ... >>> # 以下代碼會報錯,因為 'local_variable' 只存在於 'some_function' 內 >>> print(local_variable) Traceback (most recent call last): File "<stdin>", line 10, in <module> NameError: name 'local_variable' is not defined ``` ## `global` 語句 如果需要從函數內部修改全局變數,可以使用 `global` 語句: ```python >>> def spam(): ... global eggs ... eggs = 'spam' ... >>> eggs = 'global' >>> spam() >>> print(eggs) ``` 判斷變數是局部變數還是全局變數的四條規則: 1. 如果變數在全局範圍內(即在所有函數外部使用),則它總是全局變數。 2. 如果函數內有 `global` 語句對變數進行操作,那麼這個變數是全局變數。 3. 否則,如果變數在函數內的賦值語句中使用,那麼這個變數是局部變數。 4. 但是,如果變數在函數內未使用賦值語句,那麼它是全局變數。 ## 導入模組 要開始導入函數,首先需要創建一個模組。**模組是一個以 `.py` 結尾的文件,包含你希望導入到程式中的程式碼**。讓我們考慮一個包含函數 `make_pizza()` 的模組。 ### 直接導入 ```python import pizza pizza.make_pizza(16, '義式臘腸') pizza.make_pizza(12, '蘑菇') ``` ### 使用 `from` 導入特定函數 ```python from pizza import make_pizza make_pizza(16, '義式臘腸') make_pizza(12, '蘑菇') ``` ### 使用 `as` 為函數或模組取別名 ``` from pizza import make_pizza as mp mp(16, '義式臘腸') mp(12, '蘑菇') ``` ### 導入模組中的所有函數 ```python from pizza import * make_pizza(16, '義式臘腸') make_pizza(12, '蘑菇') ``` :::info :bulb: 然而,在處理你沒有編寫的大型模組時,最好避免使用這種方法:如果模組中有一個函數名稱與你項目中的現有名稱相同,可能會產生意外的結果! ::: # 4. 串列 ## 使用索引獲取值 ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> furniture[0] # 'table' >>> furniture[1] # 'chair' >>> furniture[2] # 'rack' >>> furniture[3] # 'shelf' ``` ## 負數索引 ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> furniture[-1] # 'shelf' >>> furniture[-3] # 'chair' >>> f'The {furniture[-1]} is bigger than the {furniture[-3]}' # 'The shelf is bigger than the chair' ``` ## 使用切片獲取子串列 ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> furniture[0:4] # ['table', 'chair', 'rack', 'shelf'] >>> furniture[1:3] # ['chair', 'rack'] >>> furniture[0:-1] # ['table', 'chair', 'rack'] >>> furniture[:2] # ['table', 'chair'] >>> furniture[1:] # ['chair', 'rack', 'shelf'] >>> furniture[:] # ['table', 'chair', 'rack', 'shelf'] ``` 切片完整串列會執行複製: ```python >>> spam2 = spam[:] # ['cat', 'bat', 'rat', 'elephant'] >>> spam.append('dog') >>> spam # ['cat', 'bat', 'rat', 'elephant', 'dog'] >>> spam2 # ['cat', 'bat', 'rat', 'elephant'] ``` ## 使用 `len()` 獲取串列長度 ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> len(furniture) # 4 ``` ## 使用索引修改值 ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> furniture[0] = 'desk' >>> furniture # ['desk', 'chair', 'rack', 'shelf'] >>> furniture[2] = furniture[1] >>> furniture # ['desk', 'chair', 'chair', 'shelf'] >>> furniture[-1] = 'bed' >>> furniture # ['desk', 'chair', 'chair', 'bed'] ``` ## 串接與複製 ```python >>> [1, 2, 3] + ['A', 'B', 'C'] # [1, 2, 3, 'A', 'B', 'C'] >>> ['X', 'Y', 'Z'] * 3 # ['X', 'Y', 'Z', 'X', 'Y', 'Z', 'X', 'Y', 'Z'] >>> my_list = [1, 2, 3] >>> my_list = my_list + ['A', 'B', 'C'] >>> my_list # [1, 2, 3, 'A', 'B', 'C'] ``` ## 使用 for 迴圈與串列 ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> for item in furniture: ... print(item) # table # chair # rack # shelf ``` ## 使用 `enumerate()` 獲取索引 ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> for index, item in enumerate(furniture): ... print('index', index, '- item:', item) # index: 0 - item: table # index: 1 - item: chair # index: 2 - item: rack # index: 3 - item: shelf ``` ## `in` 與 `not in` 運算子 ```python >>> 'rack' in ['table', 'chair', 'rack', 'shelf'] # True >>> 'bed' in ['table', 'chair', 'rack', 'shelf'] # False >>> 'bed' not in furniture # True >>> 'rack' not in furniture # False ``` ## 多重賦值(拆解技巧) 多重賦值技巧是一個快捷方式,讓你能夠在一行程式碼中將多個變數賦予串列中的值。這樣,比起以下方式: ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> table = furniture[0] >>> chair = furniture[1] >>> rack = furniture[2] >>> shelf = furniture[3] ``` 你可以寫成這樣: ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> table, chair, rack, shelf = furniture >>> table # 'table' >>> chair # 'chair' >>> rack # 'rack' >>> shelf # 'shelf' ``` 多重賦值技巧也可以用來交換兩個變數的值: ```python >>> a, b = 'table', 'chair' >>> a, b = b, a >>> print(a) # chair >>> print(b) # table ``` ## 添加值 ### `append()` `append` 會將一個元素添加到串列的尾端: ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> furniture.append('bed') >>> furniture # ['table', 'chair', 'rack', 'shelf', 'bed'] ``` ### `insert()` `insert` 會在指定的位置插入一個元素: ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> furniture.insert(1, 'bed') >>> furniture # ['table', 'bed', 'chair', 'rack', 'shelf'] ``` ## 刪除值 ### `del` `del` 使用索引刪除項目: ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> del furniture[2] >>> furniture # ['table', 'chair', 'shelf'] >>> del furniture[2] >>> furniture # ['table', 'chair'] ``` ## 使用 `sort()` 排序值 ```python >>> numbers = [2, 5, 3.14, 1, -7] >>> numbers.sort() >>> numbers # [-7, 1, 2, 3.14, 5] furniture = ['table', 'chair', 'rack', 'shelf'] furniture.sort() furniture # ['chair', 'rack', 'shelf', 'table'] ``` 你也可以為 `reverse` 參數傳入 `True` 來讓 `sort()` 反向排序值: ```python >>> furniture.sort(reverse=True) >>> furniture # ['table', 'shelf', 'rack', 'chair'] ``` 你也可以使用內建函數 `sorted` 返回一個新的串列: ```python >>> furniture = ['table', 'chair', 'rack', 'shelf'] >>> sorted(furniture) # ['chair', 'rack', 'shelf', 'table'] ``` ## 生成式(類似於[集合建構法](https://en.wikipedia.org/wiki/Set-builder_notation)) 串列生成式是一種特殊語法,讓我們可以從其他串列創建串列,當處理數字和有一層或兩層巢狀 `for` 迴圈時非常有用。 這是我們如何從現有的集合創建新串列,使用 `for` 迴圈: ```python >>> names = ['Charles', 'Susan', 'Patrick', 'George'] >>> new_list = [] >>> for n in names: ... new_list.append(n) ... >>> new_list # ['Charles', 'Susan', 'Patrick', 'George'] ``` 這是使用串列生成式實現的相同功能: ```python >>> names = ['Charles', 'Susan', 'Patrick', 'George'] >>> new_list = [n for n in names] >>> new_list # ['Charles', 'Susan', 'Patrick', 'George'] ``` 我們也可以對數字做相同的操作: ```python >>> n = [(a, b) for a in range(1, 3) for b in range(1, 3)] >>> n # [(1, 1), (1, 2), (2, 1), (2, 2)] ``` ### 添加條件 如果我們希望 `new_list` 只包含以 C 開頭的名稱,使用 `for` 迴圈,我們會這樣做: ```python >>> names = ['Charles', 'Susan', 'Patrick', 'George', 'Carol'] >>> new_list = [] >>> for n in names: ... if n.startswith('C'): ... new_list.append(n) ... >>> print(new_list) # ['Charles', 'Carol'] ``` 在串列生成式中,我們將 `if` 語句放在結尾: ```python >>> new_list = [n for n in names if n.startswith('C')] >>> print(new_list) # ['Charles', 'Carol'] ``` 使用 `if-else` 語句的串列推導式: ```python >>> nums = [1, 2, 3, 4, 5, 6] >>> new_list = [num*2 if num % 2 == 0 else num for num in nums] >>> print(new_list) # [1, 4, 3, 8, 5, 12] ``` :::info :bulb: 注意,大多數情況下方法會原地修改 `list`,而函數會創建一個新的 `list` ::: # 5. 元組 ## 元組資料型別 :::info :bulb: 元組和串列的主要區別在於,雖然 <code>元組</code> 是 <i>不可變的</i> 物件,<code>串列</code> 是 <i>可變的</i>。這意味著元組不能改變,而串列可以修改。元組比串列更節省記憶體。 ::: ```python >>> furniture = ('table', 'chair', 'rack', 'shelf') >>> furniture[0] # 'table' >>> furniture[1:3] # ('chair', 'rack') >>> len(furniture) # 4 ``` 元組與串列的主要區別是,像字串一樣,元組是不可變的。 ## 在 `list()` 與 `tuple()` 之間轉換 ```python >>> tuple(['cat', 'dog', 5]) # ('cat', 'dog', 5) >>> list(('cat', 'dog', 5)) # ['cat', 'dog', 5] >>> list('hello') # ['h', 'e', 'l', 'l', 'o'] ``` # 6. 字串 ## 字串的索引與切片 H e l l o w o r l d ! 0 1 2 3 4 5 6 7 8 9 10 11 ### 索引 ```python >>> spam = 'Hello world!' >>> spam[0] # 'H' >>> spam[4] # 'o' >>> spam[-1] # '!' ``` ### 切片 ```python >>> spam = 'Hello world!' >>> spam[0:5] # 'Hello' >>> spam[:5] # 'Hello' >>> spam[6:] # 'world!' >>> spam[6:-1] # 'world' >>> spam[:-1] # 'Hello world' >>> spam[::-1] # '!dlrow olleH' >>> fizz = spam[0:5] >>> fizz # 'Hello' ``` ### `in` 與 `not in` 運算子 ```python >>> 'Hello' in 'Hello World' # True >>> 'Hello' in 'Hello' # True >>> 'HELLO' in 'Hello World' # False >>> '' in 'spam' # True >>> 'cats' not in 'cats and dogs' # False ``` ## 跳脫字元 跳脫字元是透過輸入反斜線 `\` 後跟隨你想要插入的字元來創建的。 | 跳脫字元 | 顯示為 | | -------- | ----------------- | | `\'` | 單引號 | | `\"` | 雙引號 | | `\t` | 水平製表符 (Tab) | | `\n` | 換行 (換行符) | | `\\` | 反斜線 | ```python >>> print("Hello there!\nHow are you?\nI\'m doing fine.") # Hello there! # How are you? # I'm doing fine. ``` ### 原始字串 原始字串完全忽略所有跳脫字元,並將字串中出現的任何反斜線視為字面上的字元。 ```python >>> print(r"Hello there!\nHow are you?\nI\'m doing fine.") # Hello there!\nHow are you?\nI\'m doing fine. ``` ## `%` 運算元 ```python >>> name = 'Pete' >>> 'Hello %s' % name # "Hello Pete" ``` 我們可以使用 `%d` 格式規範符將整數值轉換為字串: ```python >>> num = 5 >>> 'I have %d apples' % num # "I have 5 apples" ``` ### 格式化字串或 f-字串 如果你使用的是 Python 3.6 或更新版本,字串 `f-字串` 是推薦的字串格式化方法。 <base-disclaimer> <base-disclaimer-title> 來自 <a href="https://docs.python.org/3/reference/lexical_analysis.html#f-strings">Python 3 文件</a> </base-disclaimer-title> <base-disclaimer-content> 格式化字串字面量或 f-字串是以 `f` 或 `F` 為前綴的字串文字。這些字串可以包含替換欄位,它們是用大括號 `{}` 括起來的表達式。與其他字串字面量總是具有常數值不同,格式化字串實際上是運行時評估的表達式。 </base-disclaimer-content> </base-disclaimer> ```python >>> name = 'Elizabeth' >>> f'Hello {name}!' # 'Hello Elizabeth!' ``` 甚至可以進行內聯運算: ```python >>> a = 5 >>> b = 10 >>> f'Five plus ten is {a + b} and not {2 * (a + b)}.' # 'Five plus ten is 15 and not 30.' ``` ### 多行 f-字串 ```python >>> name = 'Robert' >>> messages = 12 >>> ( ... f'Hi, {name}. ' ... f'You have {messages} unread messages' ... ) # 'Hi, Robert. You have 12 unread messages' ``` ### 數字格式化 四捨五入 ```python >>> a = 3.1415926 >>> f"{a:.2f}" # '3.14' ``` 顯示為百分比 ```python >>> a = 0.816562 >>> f"{a:.2%}" # '81.66%' ``` #### 數字格式化整理 | 數字 | 格式 | 輸出 | 描述 | | ---------- | ------ | -------- | -------------------------------------------- | | 3.1415926 | {:.2f} | 3.14 | 格式化浮點數為兩位小數 | | 3.1415926 | {:+.2f}| +3.14 | 格式化浮點數為兩位小數並顯示正負號 | | -1 | {:+.2f}| -1.00 | 格式化浮點數為兩位小數並顯示正負號 | | 2.71828 | {:.0f} | 3 | 格式化浮點數為不顯示小數 | | 4 | {:0>2d}| 04 | 用零填充數字(左側填充,寬度 2) | | 11 | {:11d} | 11 | 右對齊(預設,寬度 10) | | 11 | {:<11d}| 11 | 左對齊(寬度 10) | | 11 | {:^11d}| 11 | 置中對齊(寬度 10) | # 7. 字典 ## 使用索引運算子 `[]` 設定鍵值 ```python >>> my_cat = { ... 'size': 'fat', ... 'color': 'gray', ... 'disposition': 'loud', ... } >>> my_cat['age_years'] = 2 >>> print(my_cat) ... # {'size': 'fat', 'color': 'gray', 'disposition': 'loud', 'age_years': 2} ``` ## 使用索引運算子 `[]` 取得值 若字典中不存在該鍵,則會引發 <a target="_blank" href="https://docs.python.org/3/library/exceptions.html#KeyError">`KeyError`</a> 異常。 ```python >>> my_cat = { ... 'size': 'fat', ... 'color': 'gray', ... 'disposition': 'loud', ... } >>> print(my_cat['size']) ... # fat >>> print(my_cat['eye_color']) # Traceback (most recent call last): # File "<stdin>", line 1, in <module> # KeyError: 'eye_color' ``` ## `values()` `values()` 方法可取得字典中的 **值**: ```python >>> pet = {'color': 'red', 'age': 42} >>> for value in pet.values(): ... print(value) ... # red # 42 ``` ## `keys()` `keys()` 方法可取得字典中的 **鍵**: ```python >>> pet = {'color': 'red', 'age': 42} >>> for key in pet.keys(): ... print(key) ... # color # age ``` 由於預設情況下會遍歷鍵,因此無需使用 **.keys()**: ```python >>> pet = {'color': 'red', 'age': 42} >>> for key in pet: ... print(key) ... # color # age ``` ## `items()` `items()` 方法可取得字典中的 **項目**,並以一個 <router-link to=/cheatsheet/lists-and-tuples#the-tuple-data-type>元組</router-link> 的形式返回: ```python >>> pet = {'color': 'red', 'age': 42} >>> for item in pet.items(): ... print(item) ... # ('color', 'red') # ('age', 42) ``` 利用 `keys()`、`values()` 和 `items()` 方法,for 迴圈可以分別遍歷字典的鍵、值或鍵值對: ```python >>> pet = {'color': 'red', 'age': 42} >>> for key, value in pet.items(): ... print(f'Key: {key} Value: {value}') ... # Key: color Value: red # Key: age Value: 42 ``` ## `get()` `get()` 方法會返回具有指定鍵的項目的值;若該鍵不存在,則返回 `None`: ```python >>> wife = {'name': 'Rose', 'age': 33} >>> f'My wife name is {wife.get("name")}' # 'My wife name is Rose' >>> f'She is {wife.get("age")} years old.' # 'She is 33 years old.' >>> f'She is deeply in love with {wife.get("husband")}' # 'She is deeply in love with None' ``` 您也可以將預設的 `None` 值改成您想要的其他值: ```python >>> wife = {'name': 'Rose', 'age': 33} >>> f'She is deeply in love with {wife.get("husband", "lover")}' # 'She is deeply in love with lover' ``` ## 使用 `setdefault()` 新增項目 可以使用以下方式向字典中新增一個項目: ```python >>> wife = {'name': 'Rose', 'age': 33} >>> if 'has_hair' not in wife: ... wife['has_hair'] = True ``` 使用 `setdefault` 方法,可以使程式碼更簡潔: ```python >>> wife = {'name': 'Rose', 'age': 33} >>> wife.setdefault('has_hair', True) >>> wife # {'name': 'Rose', 'age': 33, 'has_hair': True} ``` ## 刪除項目 ### `del` `del` 命令根據指定鍵刪除項目。 ```python >>> wife = {'name': 'Rose', 'age': 33, 'hair': 'brown'} >>> del wife['age'] >>> wife # {'name': 'Rose', 'hair': 'brown'} ``` ## 檢查字典中的鍵 ```python >>> person = {'name': 'Rose', 'age': 33} >>> 'name' in person.keys() # True >>> 'height' in person.keys() # False >>> 'skin' in person # 可省略 keys() # False ``` ## 檢查字典中的值 ```python >>> person = {'name': 'Rose', 'age': 33} >>> 'Rose' in person.values() # True >>> 33 in person.values() # True ```