# Python 基礎語法 ① - 資料型態與變數 ![python-banner](https://hackmd.io/_uploads/BJX5vWrwex.png) :::info [toc] ::: <br/> 🐍 Python 中,**資料**皆有其對應的**型態**,要儲存資料以重複使用則需要一個++被命名的記憶體空間++ 稱之為**變數 (Variable)**,此外不需要宣告資料型別,直接賦值即可。 - ![image](https://hackmd.io/_uploads/ByJ_uNHwlx.png) <br/> ## 資料型態 :::success 前言: Everything in python is an object (物件) > 💡++物件就是一種模板/類別的實體,想像成一個完善的產品,有很多功能可以用++ ::: 資料型態是 Python Intepreter(解譯器) 在辨別資料格式時會參照的規則,並將其分為五大類: > 想必然 Python 的各個資料型態,也皆是不同類別的物件! <br/> - 各資料型態範例一覽: ```python '''python 單行程式碼 結尾是不必要加上分號的''' x = 10 # 整數 int y = 3.14 # 浮點數 float z = 3 + 4j # 複數 complex name = "Amy" # 字串 str is_ok = True # 布林值 bool my_list = [2, '4', 6, [8, "10"]] # 列表 list my_tuple = (1, "3", 5, (7, '9')) # 元組 tuple my_set = {1, 2, 3} # 集合 set my_dict = { 'apple': 5, 'banana': 2 } # 字典 print(type(...)) """在 python 可利用 type(object) 函式來查看物件類別""" ``` <br/> ### 1️⃣ Numeric (數值) 能夠進行++算術運算++( `+`、`-`、`*`、`**`、`/`、`//`、`%` ) 執行基本數學計算的資料型態。 1. **Integer `int`**: 所有整數都被實現為任意大小的「長整數」物件。 - `int(value, base=10)` 函式: 返回++整數物件++。 - `value`: 數字 or 字串(能夠被轉換成整數的)。 - `base`: 數值的進位制,預設為十進位。 :::spoiler 常見內建方法 - `.bit_length()`: 計算二進位數位元數。 - `.bit_count()`: 計算二進位數中 1 bit 數量。 - `.to_bytes(length, byteorder, *, signed=False)`: 返回代表數字的位元組數組。 ```python # 範例 num = 128 print(num.to_bytes(2, 'big')) # Output: b'\x00\x80' print(num.to_bytes(2, 'little')) # Output: b'\x80\x00' ``` - `.from_bytes(bytes, byteorder, *, signed=False)`: 返回代表位元組數組的數字。 ```python # 範例 byte_data = b'\x02\x01' print(int.from_bytes(byte_data, 'big')) # Output: 513 print(int.from_bytes(byte_data, 'little')) # Output: 258 ``` ::: --- 2. **Float `float`**: 浮點數數值,用於表示實數,可以包括整數或小數部分。 - `float(value)` 函式: 返回++浮點數物件++。 - `value`: 數字 or 字串(能夠被轉換成浮點數的)。 :::spoiler 常見內建方法 - `.is_integer()`: 返回 `True` 如果數值小數點部分,否則 `False`。 - `.as_integer_ratio()`: 返回一對整數(元組),代表最簡分數**分子**與**分母**。 - `.hex()`: 返回浮點數十六進位制表示法的數值以字串表示。 - `float.fromhex(string)`: 返回十六進位制數值字串的浮點數數值。 ```python # 範例 hex_str = '0x1.5000000000000p+3' print(float.fromhex(hex_str)) # Output: 10.5 ``` ::: --- 3. **Complex Number `complex`**: 表示複數,包含++實部++和++虛部++。 - `complex(value, imag)` 函式: 返回++浮點數物件++。 - `value`: 指定複數的實部 (默認為0)。 - `imag`: 指定複數的虛部 (默認為0)。 ```python # 也可以從字符串創建複數 num4 = complex('1+2j') print(num4) # 輸出: (1+2j) ``` > `complex` object 並未有許多內建方法,考慮用 `cmath` module 來做複數數學操作。 :::spoiler `cmath` 範例 ```python import cmath z = 1 + 1j modulus, phase = cmath.polar(z) print("Modulus: ", modulus) print("Phase: ", phase) sqrt_z = cmath.sqrt(z) print("Square root: ", sqrt_z) ``` ::: --- <br/> ### 2️⃣ Boolean (布林值) 在 python 中,`bool` 是 `int` 的 subclass,因此 `True` 可以被當作是 `1`,而 `False` 則是 `0`,除了從 `int` 繼承的方法和所有 Python 物件共有的基本物件方法之外,`bool` 物件++本身沒有獨特的內建方法++。 - `bool(object)` 函式: 將給定物件(值) 轉換為其對應的布林表示形式。 - `object`: 可接受任何類型物件輸入。 - ==假值==評估: `False`、`None`、數字零(`0`, `0.0`, `0j`)、空字串(`""`)、空數組(`()`、`[]`、`{}`)、`Object.__bool__()->False`、`Object.__len__()->0` - ++真值++評估: 所有其他值均視為真值,`bool()` 會傳回 `True`。這包括非空字串、非零數字、非空列表、元組、字典以及大多數自訂物件。 <br/> ### 3️⃣ Sequence (序列) :::spoiler 序列相關函數 - `len(sequence_object)`: 返回物件的元素個數。 - `max(sequence_object)`: 返回物件中的最大值。 - `min(sequence_object)`: 返回物件中的最小值。 - `sum(sequence_object)`: 返回物件中的所有元素之和(僅適用於數字序列)。 - `sorted(sequence_object, reverse=Fasle)`: 返回一個新的已排序的序列,不修改原始列表; `reverse` 參數決定是否大的數值在前,否則以小排到大。 ::: 1. String `str`: 由無意義字元所組成的資料型態,以單引號 `'` 或 雙引號 `"` 包覆,內含大量內建功能,包括用於操作、分析和格式化字串等等。 - `str(object)` 函式: 用於將其他數據類型轉換為字符串,並返回該對象的字符串表示形式。 - `object`: 可接受任何類型物件輸入。 :::spoiler `str()` 使用範例 ```python # 將整數轉換為字符串 num = 123 num_str = str(num) print(type(num_str)) # 輸出: <class 'str'> print(num_str) # 輸出: 123 # 將浮點數轉換為字符串 float_num = 3.14 float_str = str(float_num) print(type(float_str)) # 輸出: <class 'str'> print(float_str) # 輸出: 3.14 # 將布林值轉換為字符串 bool_val = True bool_str = str(bool_val) print(type(bool_str)) # 輸出: <class 'str'> print(bool_str) # 輸出: True # 將列表轉換為字符串 my_list = [1, 2, 3] list_str = str(my_list) print(type(list_str)) # 輸出: <class 'str'> print(list_str) # 輸出: [1, 2, 3] # 將字典轉換為字符串 my_dict = {'a': 1, 'b': 2} dict_str = str(my_dict) print(type(dict_str)) # 輸出: <class 'str'> print(dict_str) # 輸出: {'a': 1, 'b': 2} ``` ::: > 🔗 String 內建方法: [Python String Methods](https://www.w3schools.com/python/python_ref_string.asp) --- <br/> 2. List `list`: 儲存++多個元素++(多維資料)的資料型態,這些元素可以是不同的資料型態,並且可以重複。列表通過方括號 `[]` 來表示並且內容是可改變的,這意味可以修改列表中的元素、新增元素或移除元素 (CRUD)。 - `list(iterable)` 函式: 將一個可疊代物件(例如字串、元組或集合) 轉換為列表。 :::spoiler 常見內建方法 - `append(element)`: 將一個元素添加到列表的末尾。 - `insert(index, element)`: 在指定的索引位置插入一個元素。 - `extend(another_list)`: 將另一個列表的所有元素添加到當前列表的末尾。 - `remove(element)`: 移除列表中第一個匹配到的元素。 - `pop([index])`: 移除並返回指定索引位置的元素,如果不指定索引,則移除並返回列表的最后一个元素。 - `index(element)`: 返回列表中第一個匹配到的元素的索引。 - `count(element)`: 返回列表中某個元素出现的次数。 - `sort(reverse=False)`: 對列表中的元素進行排序,默認升序,可以使用 `reverse=True` 做反序排序。 - `reverse()`: 反轉列表中的元素順序。 - `copy()`: 返回列表的淺拷貝。 - `clear()`: 移除列表中的所有元素。 ```python # 範例 my_list = [1, 2, 3, 'apple', 'banana'] # 列表長度 print(len(my_list)) # 輸出: 5 # 添加元素 my_list.append(4) print(my_list) # 輸出: [1, 2, 3, 'apple', 'banana', 4] # 插入元素 my_list.insert(2, 'orange') print(my_list) # 輸出: [1, 2, 'orange', 3, 'apple', 'banana', 4] # 移除元素 my_list.remove('apple') print(my_list) # 輸出: [1, 2, 'orange', 3, 'banana', 4] # 移除並返回元素 removed_element = my_list.pop(1) print(my_list) # 輸出: [1, 'orange', 3, 'banana', 4] print(removed_element) # 輸出: 2 # 排序 numbers = [3, 1, 4, 1, 5, 9, 2, 6] numbers.sort() print(numbers) # 輸出: [1, 1, 2, 3, 4, 5, 6, 9] # 反轉 numbers.reverse() print(numbers) # 輸出: [9, 6, 5, 4, 3, 2, 1, 1] # 拷貝 new_list = my_list.copy() print(new_list) # 輸出: [1, 'orange', 3, 'banana', 4] # 清空 my_list.clear() print(my_list) # 輸出: [] ``` ::: --- 3. Tuple `tuple`: 類似列表型態,但是元組物件是++不可變序列++,且其內建方法有限。 - `tuple(iterable)`: 接受一個可迭代物件並將其元素轉換為不可變的元組 (_Read-Only_)。 ```python # 範例 # creating empty tuple empty_tuple1 = () empty_tuple2 = tuple() print(empty_tuple1, empty_tuple2) # creating a tuple from a list. my_list = [1, 2, 3] new_tuple = tuple(my_list) print(new_tuple) # output: (1, 2, 3) # creating a tuple from a string. my_string = "Python" char_tuple = tuple(my_string) print(char_tuple) # output: ('P', 'y', 't', 'h', 'o', 'n') ``` - 主要方法: - `tuple.count(value)`: 回傳指定值在元組中出現的次數。 - `tuple.index(value, start=0, end=len(tuple))`: 回元組中指定值++首次++出現的索引。可以傳入可選的 `start` 和 `end` 參數,以便在元組的特定切片內進行搜尋。如果未找到該值,則會引發 `ValueError` 錯誤。 --- <br/> ### 4️⃣ Set (集合) 集合用於儲存++無序++且++不重複++的元素集合。是可以變動的,也意味著可以新增或移除元素。集合的特性使其適合於執行諸如求交集、聯集、差集等數學集合運算。 - `set(iterable)` 函式: 將可迭代物件轉換為集合,自動去除重複的元素,並返回新的集合物件。 ```python # 範例 # creating empty set empty_set1 = {} empty_set2 = set() print(empty_set1, empty_set2) # output: {} set() # creating a set from a list. my_list = [1, 2, 2, 3, 4, 4, 4, 5] my_set = set(my_list) print(my_set) # 輸出: {1, 2, 3, 4, 5} (順序可能不同) # creating a set from a string. my_string = "hello" my_set = set(my_string) print(my_set) # 輸出: {'h', 'e', 'l', 'o'} (順序可能不同) ``` :::spoiler 常見內建方法 <br/> | 函式 | 集合方法 | |-|-| | `add(element)` | 在集合中加入指定元素。如果該元素已存在,則集合保持不變。 | | `clear()` | 從集合中刪除所有元素,使其成為空集合。 | | `copy()` | 傳回集合的淺拷貝。 | | `pop()` | 從集合中移除並傳回任意一個元素。由於集合是無序的,因此無法保證移除的是哪個元素。如果集合為空,則會引發 `KeyError`。 | | `remove(element)` | 從集合中刪除指定元素。如果未找到該元素,則引發 KeyError。 | | `discard(element)` | 如果存在,則從集合中移除指定元素。與 `remove()` 不同,如果找不到該元素,則不會引發 `KeyError`。 | | `difference(other_set)` | 傳回一個新集合,其中包含原始集合中存在但不存在於 `other_set` 中的元素。此操作也可以使用 ==-== 運算子實作。 | | `difference_update(other_set)` | 從原始集合中刪除在 `other_set` 中也存在的元素。這會對集合進行修改。也可以使用 ==-\=== 運算子實現此操作。 | | `union(other_set)` | 傳回一個包含原始集合和 `other_set` 中所有唯一元素的新集合。也可以使用 ==\|== 運算子實作。 | | `update(other_set)` | 將 `other_set` 中所有唯一元素加入到原始集合中。這會就地修改集合。也可以使用 ==\|\=== 運算子來實現此操作。 | | `issuperset(other_set)` | 如果 `other_set` 的所有元素都存在於原始集合中,則傳回 `True`,否則傳回 `False`。這也可以使用 ==>\=== 運算子實現。 | | `issubset(other_set)` | 如果原始集合的所有元素都存在於 `other_set` 中,則傳回 `True`,否則傳回 `False`。這也可以使用 ==<\=== 運算子實現。 | | `intersection(other_set)` | 傳回一個新集合,其中包含原始集合和 `other_set` 共有的元素。也可以使用 ==&== 運算子實作。 | | `intersection_update(other_set)` | 透過只保留原始集合和 `other_set` 共有的元素來更新原始集合。這會就地修改集合。也可以使用 ==&\=== 運算子來實現。 | | `symmetric_difference(other_set)` | 傳回一個新集合,該集合包含原集合或 `other_set` 中的元素,但不同時存在於兩者中。此操作也可以使用 ==^== 運算子實現。 | | `symmetric_difference_update(other_set)` | 更新原始集合,僅保留原始集合或 `other_set` 中存在的元素,但不同時存在於兩者中。這會就地修改集合。此操作也可以使用 ==^\=== 運算子實現。 | | `isdisjoint(other_set)` | 如果集合與 `other_set` 沒有共同的元素,則傳回 `True`,否則傳回 `False`。 | ::: <br/> ### 5️⃣ Dictionary (字典) 字典是一個儲存許多鍵與值配對的資料型態,物件提供了多種與其++鍵值對++互動的方法。這些方法允許執行各種操作,包括新增、刪除、存取和迭代元素。 - `dict(keyword arguments,)` 函式: 用於建立並返回字典物件。字典是一個可變的、無序的鍵值對集合,其中每個鍵都是唯一的,並映射到一個特定的值 (Hash Table)。 - `key1=arg1, key2=arg2`:Optional。可設定任意數量的關鍵字參數與值配對,並以逗號分隔:`key = value, key = value ...` ```python # 範例 # creating empty dictionary my_dict = dict() # Creating a dictionary from keyword arguments. person = dict(name="Alice", age=30, city="New York") # Creating a dictionary from an iterable of key-value pairs (e.g., a list of tuples) data = [('one', 1), ('two', 2), ('three', 3)] numbers = dict(data) # Creating a dictionary from a mapping object (e.g., another dictionary) original_dict = {'a': 1, 'b': 2} new_dict = dict(original_dict) ``` > 🔗 Dictionary 內建方法: [Python Dictionary Methods](https://www.w3schools.com/python/python_ref_functions.asp) <br/> ## 變數 Python 中,**變數** 是儲存資料的容器,它們可以被賦予一個名稱,以便在程式碼中引用和操作。 變數可以儲存不同型別的資料,並且可以在程式執行過程中改變其值。 1. 基本概念 - **儲存資料**: 變數就像一個標籤,指向記憶體中儲存資料的位置。 - **動態型別**: 變數是動態型別的,這意味不需要明確宣告變數的資料型別,Python 會根據賦予的值自動判斷。 - **可變性**: 變數的值可以在程式執行過程中改變。 2. 變數的命名規則 - 變數名稱必須以字母或底線開頭。 - 變數名稱可以包含字母、數字和底線。 - 變數名稱不能以數字開頭。 - 變數名稱是區分大小寫的 (e.g: `age` 和 `Age` 是不同的變數)。 3. 範例 ```python # 定義一個整數變數 x = 10 print(x) # 輸出: 10 # 定義一個字串變數 name = "Alice" print(name) # 輸出: Alice # 多重賦值 x, y, z = "Orange", "Banana", "Cherry" print(x, y, z) # 改變變數的值 x = 20 print(x) # 輸出: 20 # 使用更具描述性的變數名稱 student_name = "Bob" print(student_name) # 輸出: Bob ``` 4. 賦與拷貝 在 Python 中,**變數本質上是參考(Reference)記憶體中的資料**,這表示: ```python a = [1, 2, 3] b = a b[0] = 100 print(a) # [100, 2, 3] ❗️a 也跟著被改變了 ``` :::warning 因為 `b = a` 是讓 `b` 指向和 `a` 同一個 list,而不是複製內容! ::: a. **Shallow Copy** (淺拷貝) 範例 ```python import copy a = [[1, 2], [3, 4]] b = copy.copy(a) b[0][0] = 999 print(a) # [[999, 2], [3, 4]] ❗️內層仍連動 '''外層 list 被複製,但內層仍然是同一個物件''' ``` b. **Deep Copy** (深拷貝) 範例 ```python import copy a = [[1, 2], [3, 4]] b = copy.deepcopy(a) b[0][0] = 999 print(a) # [[1, 2], [3, 4]] ✅ 完全獨立 '''使用 deepcopy 可以確保所有內部物件都被獨立複製''' ``` ::: spoiler **Python `copy`(拷貝) 比較表** <br/> | 概念 | Python 賦值 | Python 淺拷貝 | Python 深拷貝 | |-|-|-|-| | 外層物件 | 共用 | 複製 | 複製 | 複製(bitwise) | 複製(new 出新記憶體) | | 內層物件 | 共用 | 共用 | 複製 | 共用指標 | 複製記憶體內容 | | 使用場景 | 快速參考 | 效率佳但要小心 | 完全獨立資料 | 預設行為 | 防止共用造成錯誤 | ::: c. 🧪 小測驗 ```python x = [1, 2, 3] y = x z = x.copy() y[0] = 99 z[1] = 77 print(x) # ? print(y) # ? print(z) # ? ``` <br/> ## 小結 - Python 是 **動態型別語言**,不需事先宣告變數型別,會根據賦值自動判斷。 - 常見的資料型態可分為五大類: 1. **Numeric 數值型別**:`int`、`float`、`complex` 2. **Boolean 布林型別**:`True` / `False`,常用於邏輯判斷 3. **Sequence 序列型別**:`str`、`list`、`tuple`(具順序,可用索引存取) 4. **Set 集合型別**:`set`,無順序、不重複 5. **Dictionary 字典型別**:`dict`,以鍵值對(key-value)儲存資料 - **變數命名**需遵循規範,並具描述性,便於閱讀與維護。 - 使用 `type()` 可以隨時檢查變數的資料型態。 - 變數儲存的是「**指向資料的參考(reference)**」,而非值的複製,尤其在處理 list、dict 時要注意「共享 vs 拷貝」的差異。 - 遇到多層資料結構時可使用 `copy()` 或 `deepcopy()` 做資料複製,避免非預期的修改行為。 <br/> :::spoiler __Relevant Resources__ [Python Variables](https://www.w3schools.com/python/python_variables.asp) [🔁 上一節: **環境設定與標準輸入輸出**](/rirdIkdWRh6Thlx93gJ6YQ) [🔁 下一節: **條件與流程控制 (if, for, while)**](/8IoFyK7ISEqfk4qN4PLApg) :::