# Python 基礎語法 ① - 資料型態與變數

:::info
[toc]
:::
<br/>
🐍 Python 中,**資料**皆有其對應的**型態**,要儲存資料以重複使用則需要一個++被命名的記憶體空間++ 稱之為**變數 (Variable)**,此外不需要宣告資料型別,直接賦值即可。
- 
<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)
:::