Python copy() - List 複製

copy() 方法用來建立 list 的淺拷貝(shallow copy)。

基本用法

original = [1, 2, 3]
copied = original.copy()

print(original)  # [1, 2, 3]
print(copied)    # [1, 2, 3]

# 修改複製的 list 不影響原 list
copied.append(4)
print(original)  # [1, 2, 3]
print(copied)    # [1, 2, 3, 4]

為什麼需要 copy()

直接賦值只會建立參照,不是複製:

original = [1, 2, 3]
not_a_copy = original  # 只是參照同一個 list

not_a_copy.append(4)
print(original)    # [1, 2, 3, 4](被影響了!)
print(not_a_copy)  # [1, 2, 3, 4]

複製 list 的方法

original = [1, 2, 3]

# 方法 1:copy() 方法
copied1 = original.copy()

# 方法 2:切片
copied2 = original[:]

# 方法 3:list() 建構函數
copied3 = list(original)

# 方法 4:list comprehension
copied4 = [x for x in original]

# 都是獨立的複本
copied1.append(4)
print(original)  # [1, 2, 3]
print(copied1)   # [1, 2, 3, 4]

淺拷貝(Shallow Copy)

copy() 是淺拷貝,只複製第一層:

original = [[1, 2], [3, 4]]
copied = original.copy()

# 修改第一層沒問題
copied.append([5, 6])
print(original)  # [[1, 2], [3, 4]]
print(copied)    # [[1, 2], [3, 4], [5, 6]]

# 但內層物件是共用的!
copied[0].append(999)
print(original)  # [[1, 2, 999], [3, 4]](被影響了!)
print(copied)    # [[1, 2, 999], [3, 4], [5, 6]]

深拷貝(Deep Copy)

使用 copy.deepcopy() 進行深拷貝:

import copy

original = [[1, 2], [3, 4]]
deep_copied = copy.deepcopy(original)

# 修改內層也不會影響原本的
deep_copied[0].append(999)
print(original)    # [[1, 2], [3, 4]](不受影響)
print(deep_copied) # [[1, 2, 999], [3, 4]]

實際範例

保存狀態

def save_state(history, current):
    history.append(current.copy())

history = []
data = [1, 2, 3]

save_state(history, data)
data.append(4)
save_state(history, data)
data.append(5)
save_state(history, data)

print(history)  # [[1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]

避免修改原始資料

def process_data(data):
    # 複製後處理,避免影響原資料
    working_copy = data.copy()
    working_copy.sort()
    return working_copy

original = [3, 1, 4, 1, 5]
sorted_data = process_data(original)

print(original)     # [3, 1, 4, 1, 5](不變)
print(sorted_data)  # [1, 1, 3, 4, 5]

函數參數的防禦性複製

def add_item(items, item):
    # 建立新 list 而不是修改傳入的
    new_items = items.copy()
    new_items.append(item)
    return new_items

original = [1, 2, 3]
new_list = add_item(original, 4)

print(original)  # [1, 2, 3]
print(new_list)  # [1, 2, 3, 4]

深拷貝複雜結構

import copy

game_state = {
    "players": [
        {"name": "Alice", "score": 100, "inventory": ["sword", "shield"]},
        {"name": "Bob", "score": 80, "inventory": ["bow"]}
    ],
    "level": 5
}

# 需要深拷貝來完全複製
saved_state = copy.deepcopy(game_state)

# 修改原始狀態
game_state["players"][0]["score"] = 150
game_state["players"][0]["inventory"].append("potion")

print(saved_state["players"][0]["score"])      # 100(不變)
print(saved_state["players"][0]["inventory"])  # ['sword', 'shield'](不變)

常見錯誤

忘記複製

# 錯誤:會修改原 list
def remove_negatives(numbers):
    for n in numbers[:]:  # 需要先複製
        if n < 0:
            numbers.remove(n)
    return numbers

# 正確:使用 list comprehension 建立新 list
def remove_negatives(numbers):
    return [n for n in numbers if n >= 0]

淺拷貝陷阱

# 陷阱:淺拷貝不會複製內層
matrix = [[0] * 3 for _ in range(3)]
row_copy = matrix[0].copy()  # 這是淺拷貝

# 但如果是這樣就有問題
matrix = [[0] * 3] * 3  # 三列都是同一個 list!
matrix[0][0] = 1
print(matrix)  # [[1, 0, 0], [1, 0, 0], [1, 0, 0]]

效能考量

  • 淺拷貝 copy():O(n)
  • 深拷貝 deepcopy():O(n × m),其中 m 是巢狀深度

只有在需要時才使用深拷貝,因為它比較慢。