Python 新手最容易踩的 10 个语法坑
很多人觉得 Python 语法简洁,上手快。但正是这种"简洁",藏了不少让人掉坑的细节。以下 10 个坑,几乎每个新手都踩过至少一半。
1. 可变默认参数
python
python
def add(item, lst=[]):
lst.append(item)
return lst
print(add(1)) # [1]
print(add(2)) # [1, 2] ← 意外!
默认参数只在函数定义时求值一次,lst=[] 是同一个对象。正确写法:
python
python
def add(item, lst=None):
if lst is None:
lst = []
lst.append(item)
return lst
2. 闭包延迟绑定
ini
python
funcs = [lambda: i for i in range(5)]
print([f() for f in funcs]) # [4, 4, 4, 4, 4]
lambda 里的 i 不是"捕获值",而是"引用变量"。循环结束后 i=4,所以全返回 4。
修复 :lambda i=i: i,用默认参数锁住当前值。
3. is vs ==
ini
python
a = 256
b = 256
print(a is b) # True(小整数池)
a = 257
b = 257
print(a is b) # False!
is 比较的是内存地址 ,== 才比较值。判断相等,永远用 ==。is 只该用于和 None 比较(if x is None)。
4. 缩进导致的逻辑错误
python
python
def foo(x):
if x > 0:
print("正数")
return "完成" # 这个 return 不在 if 里
新手常以为缩进只是"格式",其实它是语法本身。Tab 和空格混用会直接报错,PEP 8 规定统一用 4 个空格。
5. 修改正在遍历的列表
ini
python
nums = [1, 2, 3, 4]
for n in nums:
if n % 2 == 0:
nums.remove(n)
print(nums) # [1, 3] → 但如果是 [2,4,6,8] 会出问题
遍历中删除元素会导致索引错乱。正确做法:
ini
python
nums = [n for n in nums if n % 2 != 0]
# 或
for n in nums[:]: # 遍历副本
6. 字符串不可变,但变量名可以"变"
ini
python
s = "hello"
s = s + " world" # 不是在原字符串上改,而是创建了新对象
很多新手以为字符串拼接是"修改",其实每次都生成新对象。大量拼接时,用 ''.join(list) 或 f-string 性能好得多。
7. 浅拷贝 vs 深拷贝
css
python
import copy
a = [[1, 2], [3, 4]]
b = a.copy() # 浅拷贝
b[0][0] = 999
print(a) # [[999, 2], [3, 4]] ← 原列表也被改了!
c = copy.deepcopy(a) # 深拷贝才真正独立
列表的 .copy()、list()、切片 [:] 都是浅拷贝。嵌套结构必须用 copy.deepcopy()。
8. except 捕获范围太大
python
python
try:
result = 10 / 0
except: # 什么都捕获,包括系统退出信号
print("出错了")
裸 except 会捕获 KeyboardInterrupt,导致你按 Ctrl+C 都关不掉程序。始终写具体异常:
python
python
except ZeroDivisionError:
print("除零了")
9. 字典键必须可哈希
ini
python
d = {[1, 2]: "value"} # TypeError: unhashable type: 'list'
列表、字典、集合都不能当字典的 key,因为它们可变。元组可以。
10. for...else 和 while...else
python
python
for i in range(5):
if i == 10:
break
else:
print("循环正常结束") # 会执行!
else 在循环没有被 break 打断 时才执行。这个设计是故意的(用于搜索场景),但 90% 的新手第一次见到都会困惑。反过来说:else 跟着 for,不是跟着 if。
总结
| 坑 | 本质原因 |
|---|---|
| 默认参数 | 对象在定义时创建,不是调用时 |
| 闭包延迟绑定 | 引用变量,不是捕获值 |
is vs == |
混淆了"身份"和"值" |
| 缩进错误 | 把 Python 当纯文本语言 |
| 遍历中修改 | 索引在变,迭代器跟不上 |
| 字符串拼接 | 误以为字符串可变 |
| 浅拷贝 | 不理解引用传递 |
| 裸 except | 不知道异常体系 |
| 字典 key | 不了解可哈希规则 |
| for-else | 不知道 else 的真实语义 |
Python 的"简单"是给老手的,新手恰恰要在这些"简单"里保持警惕。踩过这些坑,才算真正入门。