Python 以其簡單性和可靠性而聞名,但即使是最優秀的開發者也會遇到神秘的錯誤和意外的錯誤。有些陷阱是顯而易見的,但其他的則潛伏在陰影中,等待破壞你的腳本。如果你曾經對代碼中的某個問題感到困惑,那麼這些隱藏的 Python 殺手之一很可能是罪魁禍首。

這裡有 10 件你可能不知道會破壞你的 Python 腳本的事情——以及如何避免它們。
1. 可變的預設參數
問題:在函數定義中使用可變對象(如列表或字典)作為默認參數可能會導致意外行為。
# Bad practice
def add_item(item, items=[]):
items.append(item)
return items
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] – Wait, what?!
修正方法:始終使用不可變的默認值,如 None,並在函數內部初始化。
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
2. 混合環境中的不正確縮排
問題: 混合使用制表符和空格可能會導致難以發現的錯誤,特別是在協作項目時。
# Mixing spaces and tabs
if True:
print("This will fail in some environments!")
修正方法: 使用一致的縮排風格 — 最好是空格。配置您的編輯器自動將制表符轉換為空格。
3. 在迭代時修改列表
問題: 在迴圈中更改列表可能會導致跳過元素和不可預測的行為。
numbers = [1, 2, 3, 4, 5]
for num in numbers:
if num % 2 == 0:
numbers.remove(num) # Oops! Skips elements
修正方法:遍歷列表的副本或使用列表推導式。
numbers = [num for num in numbers if num % 2 != 0]
4. 使用 is 而不是 == 進行比較
問題: is 運算符檢查對象的身份,而不是相等性。
x = 256
y = 256
print(x is y) # True (because of interning)
x = 300
y = 300
print(x is y) # False!
修正方法: 使用 == 進行值比較,並且僅在必要時使用 is 進行身份檢查。
5. 預設字典鍵的意外行為
問題: 在常規字典中訪問缺失的鍵會引發 KeyError,而 defaultdict 會自動創建缺失的鍵,有時會導致微妙的錯誤。
from collections import defaultdict
d = defaultdict(list)
d["missing"].append(42) # Key is created automatically!
修正方法: 當您需要安全查找時,使用 dict.get()。
value = my_dict.get("missing", [])
6. 迴圈變數洩漏到全域範圍
問題:在 Python 2 中,循環變量會洩漏到循環外,導致意外的修改。
for i in range(5):
pass
print(i) # i is still accessible
修正方法: 使用函數範圍來封裝變量,或使用 Python 3,這已經修復。
7. 浮點數精度錯誤
問題: 浮點運算可能導致微小的不準確性。
print(0.1 + 0.2) # 0.30000000000000004
修正方法: 當精確度至關重要時,使用 decimal 模組。
from decimal import Decimal
print(Decimal("0.1") + Decimal("0.2")) # 0.3
8. 多執行緒中的競爭條件
問題:同時訪問共享資源的線程可能會導致不可預測的行為。
import threading
def increment(counter):
for _ in range(1000):
counter["count"] += 1
counter = {"count": 0}
threads = [threading.Thread(target=increment, args=(counter,)) for _ in range(10)]
for t in threads:
t.start()
for t in threads:
t.join()
print(counter["count"]) # Not 10000!
修正方法: 使用線程安全的結構,如 threading.Lock。
9. 循環導入
問題:兩個模組互相導入可能會導致ImportError。
# module_a.py
import module_b
# module_b.py
import module_a # Circular import error!
解決方案: 通過使用本地導入或重構代碼來打破依賴關係。
10. 默默忽略例外
問題: 捕捉所有異常而不正確處理會使調試變得困難。
try:
risky_function()
except Exception:
pass # Silent failure!
修正方法: 記錄例外並在可能的情況下處理特定的例外。
import logging
try:
risky_function()
except ValueError as e:
logging.error(f"Value error: {e}")
結論
Python 是一種強大的語言,但即使是經驗豐富的開發人員也可能會陷入這些陷阱。通過了解這些隱藏的陷阱,您可以編寫更可靠、可維護且無錯誤的 Python 代碼。