Python 新手最容易踩的 10 个语法坑

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...elsewhile...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 的"简单"是给老手的,新手恰恰要在这些"简单"里保持警惕。踩过这些坑,才算真正入门。

相关推荐
二月龙1 小时前
Python 迭代器与生成器精讲:大幅降低内存占用
后端
AINative软件工程2 小时前
Tool Schema 写得好,模型少出错:5 个工程师必知的设计原则
后端·openai
AINative软件工程2 小时前
AI 写的代码,Review 要怎么改?我们团队的 15 条 PR 检查清单
后端·openai
武子康2 小时前
Java-21 深入浅出 MyBatis 手写ORM框架2 手写Resources、MappedStatment、XMLBuilder等
java·后端
techdashen2 小时前
在 Fly.io 上使用 Rust 构建远程开发环境:从 Tokio 到 eBPF
开发语言·后端·rust
摇滚侠3 小时前
Spring 零基础入门到进阶 面向切面 AOP 52-60
java·后端·spring
雪隐3 小时前
AI股票小助手07-TA-Lib 技术指标计算实战
人工智能·后端
掘金者阿豪3 小时前
一本书读懂微积分!
后端
Cosolar3 小时前
深入理解 LangChain Callback 机制:从入门到实战
人工智能·后端·面试