Python 課程 ── 運算子(Operators)
主題:指派運算子(=, +=, -=, …)
簡介
在程式語言中,**指派(assignment)**是最基礎、也是最常見的操作之一。它負責把資料(值)存入變數,讓程式的後續邏輯可以使用與修改這些資料。Python 提供了多種指派運算子,從最簡單的等號 = 到結合算術、位元或容器操作的複合指派(+=, -= …),它們不僅讓程式碼更簡潔,也能提升效能與可讀性。
了解指派運算子的行為與細節,對 初學者 來說是建立正確程式思維的第一步;對 中級開發者 而言,則是撰寫高效、易維護程式碼的關鍵技巧。本篇文章將從概念說明、實作範例、常見陷阱到最佳實踐,完整呈現 Python 指派運算子的使用方式與實務應用。
核心概念
1. 基本指派 =
最常見的指派形式是使用等號 =,將右側的表達式結果儲存到左側的變數名稱。
# 基本指派範例
x = 10 # 把整數 10 指派給變數 x
name = "Alice" # 把字串指派給變數 name
lst = [1, 2, 3] # 把列表指派給變數 lst
注意:
=只負責「把值」放入變數,不會比較兩個變數是否相等(比較使用==)。
2. 複合指派(Compound Assignment)
複合指派結合了 算術/位元運算 與 指派,語法為 運算子=(例如 +=、-=、*= …)。其背後的運作流程等價於:
a = a <operator> b
但在執行上會直接在原位(in‑place)修改變數,對可變物件(mutable)尤其有效率。
2.1 加法指派 +=
counter = 0
counter += 5 # 等同於 counter = counter + 5
print(counter) # 5
- 字串 也支援
+=,會產生新字串:
msg = "Hello"
msg += ", World!" # 等同於 msg = msg + ", World!"
print(msg) # Hello, World!
2.2 減法指派 -=、乘法指派 *=、除法指派 /=、取餘指派 %=
x = 20
x -= 4 # x = x - 4 -> 16
x *= 2 # x = x * 2 -> 32
x /= 8 # x = x / 8 -> 4.0
x %= 3 # x = x % 3 -> 1.0
2.3 位元指派 &=, |=, ^=, >>=, <<=
flags = 0b1010 # 10 (十進位)
flags |= 0b0101 # 設定第 0、2 位為 1 -> 0b1111
flags ^= 0b0011 # 進行 XOR -> 0b1100
flags <<= 2 # 左移 2 位 -> 0b110000
print(bin(flags)) # 0b110000
2.4 整除指派 //= 與指數指派 **=
y = 17
y //= 3 # y = y // 3 -> 5 (向下取整)
y **= 2 # y = y ** 2 -> 25
2.5 列表、集合與字典的原位更新
- 列表的
+=會把右側的可迭代物件展開後 原位延伸(不會產生新列表):
numbers = [1, 2, 3]
numbers += [4, 5] # 等同於 numbers.extend([4,5])
print(numbers) # [1, 2, 3, 4, 5]
- 集合的
|=、&=、-=會在原位完成集合運算:
a = {1, 2, 3}
b = {3, 4, 5}
a |= b # a = a.union(b) 原位更新
print(a) # {1, 2, 3, 4, 5}
- 字典的
|=(Python 3.9+)可以合併兩個字典:
d1 = {"x": 1, "y": 2}
d2 = {"y": 3, "z": 4}
d1 |= d2 # d1 = d1 | d2
print(d1) # {'x': 1, 'y': 3, 'z': 4}
3. 多重指派(Multiple Assignment)
Python 允許一次指派多個變數,語法上看起來像「解構賦值」:
a, b, c = 1, 2, 3 # a=1, b=2, c=3
x = y = z = 0 # 同時把 0 指派給三個變數
此特性常用於 交換變數值,不需要暫存變數:
i, j = 5, 10
i, j = j, i # 交換後 i=10, j=5
程式碼範例
以下示範 5 個常見且實用的指派運算子應用,附上說明與可能的錯誤情境。
範例 1:計算累積總和
total = 0
for i in range(1, 6): # 1~5
total += i # 每次迭代把 i 加到 total
print("1~5 的總和:", total) # 15
說明:
+=讓累加的寫法更簡潔,避免每次都寫total = total + i。
範例 2:字串緩衝區(String Buffer)
buffer = ""
for word in ["Python", "是", "一門", "好學的", "語言"]:
buffer += word + " " # 逐字串拼接
print(buffer.strip())
# 輸出: Python 是 一門 好學的 語言
注意:在大量字串拼接時,
+=會產生多個暫時字串,若效能敏感,可改用list+''.join()。
範例 3:原位更新列表
data = [10, 20, 30]
extra = [40, 50]
data += extra # 等同於 data.extend(extra)
print(data) # [10, 20, 30, 40, 50]
重點:
data本身被改變,若有其他變數指向同一列表,它們也會同步看到變化。
範例 4:位元旗標(Flag)操作
READ = 0b001 # 1
WRITE = 0b010 # 2
EXEC = 0b100 # 4
perm = 0 # 初始沒有權限
perm |= READ # 開啟讀取權限
perm |= WRITE # 同時開啟寫入權限
print(bin(perm)) # 0b011
# 檢查是否有執行權限
if perm & EXEC:
print("可以執行")
else:
print("沒有執行權限")
說明:使用
|=把多個旗標合併成一個整數;&用於檢查特定位元。
範例 5:字典合併(Python 3.9+)
default_cfg = {"host": "localhost", "port": 3306, "debug": False}
user_cfg = {"port": 8080, "debug": True}
# 使用 |= 直接在 default_cfg 上更新
default_cfg |= user_cfg
print(default_cfg)
# {'host': 'localhost', 'port': 8080, 'debug': True}
最佳實踐:若需要保留原始設定,可先做
copy()再使用|=。
常見陷阱與最佳實踐
| 陷阱 | 說明 | 建議的做法 |
|---|---|---|
| 可變物件的別名(alias) | list_a = list_b 只會把兩個變數指向同一個列表,之後的 += 會同時改變兩者。 |
若需要 複製,使用 list_a = list_b.copy() 或 list_a = list(list_b)。 |
字串大量 += |
每次 += 會產生新字串,導致 O(n²) 的時間與記憶體開銷。 |
改用 list 收集片段,最後 ''.join(list)。 |
除法指派 /= 產生浮點數 |
在 Python 3 中,/= 永遠回傳 float,即使兩個整數相除。 |
若需要整數除法,使用 //=。 |
| 位元指派的優先順序 | 如 a <<= 1 + 2 會先算 1 + 2 再左移。但 a <<= 1 + 2 與 a <<= (1 + 2) 同等。 |
使用括號明確表達意圖,避免混淆。 |
| **字典 ` | =` 的版本限制** | ` |
最佳實踐
明確使用可變與不可變物件
- 對 不可變(int、float、str、tuple)使用
+=時,其實是 重新綁定,不會改變原始物件。 - 對 可變(list、dict、set)使用
+=、|=等會 原位修改,要注意別名問題。
- 對 不可變(int、float、str、tuple)使用
在迴圈內盡量避免字串
+=- 若字串長度可能很大,改用
io.StringIO或list+join。
- 若字串長度可能很大,改用
使用複合指派提升可讀性
counter += 1明顯表達「累加 1」的意圖,較counter = counter + 1更直觀。
善用多重指派與解構賦值
x, y = y, x用於變數交換,避免臨時變數。a, *b = range(5)可快速取得「首項」與「剩餘」集合。
在函式內部避免不必要的全域變數變更
- 若要在函式內部累計結果,考慮回傳新值或使用
nonlocal/global明確聲明。
- 若要在函式內部累計結果,考慮回傳新值或使用
實際應用場景
| 場景 | 典型指派運算子 | 為何適合 |
|---|---|---|
| 計算機統計(例如每日銷售額累加) | +=、-= |
累計/扣除操作頻繁,使用 +=/-= 可保持程式碼簡潔。 |
| 資料清理(把多個列表合併成一個) | +=(列表) |
list.extend() 的語法糖,使合併更直觀。 |
| 權限管理(檔案或使用者的位元旗標) | ` | =, &=, ^=` |
| 設定合併(預設設定與使用者自訂) | ` | =`(字典) |
| 即時圖形或遊戲開發(位置、速度更新) | +=, -=、*= |
物件的座標、速度常以向量形式更新,複合指派讓運算更自然。 |
| 大量文字產生(報表、HTML 模板) | list.append() + ''.join()(避免 +=) |
提升效能,避免字串大量重新分配。 |
| 演算法實作(快速排序、合併排序中的索引移動) | +=, -=、>>=、<<= |
索引的前後移動或位元操作常用於優化。 |
總結
指派運算子是 Python 程式設計的基石,從最簡單的 = 到功能強大的 +=、|=、>>= 等,掌握它們的語意與執行機制,能讓程式碼:
- 更簡潔:減少重複寫
變數 = 變數 <op> 值的樣板。 - 更高效:對可變物件的原位更新避免不必要的記憶體分配。
- 更易讀:使用直觀的符號表達「累加、減除、合併」等常見意圖。
在實務開發中,請特別留意 可變物件的別名、字串大量 += 的效能問題,以及 語法支援的版本限制。遵循本文的 最佳實踐,配合適當的測試與除錯,您將能寫出既 乾淨 又 高效 的 Python 程式。
祝您在 Python 的旅程中,玩得開心、寫得順手! 🎉