在Python编程中,尽管语言设计相对简洁易懂,但初学者乃至有一定经验的开发者仍可能遇到一些常见的错误或陷阱。以下是一些容易出错的地方,按类别列出并简要说明:
-
变量作用域(Scope)混淆
错误示例:
x = 10
def func():
print(x) # UnboundLocalError
x = 5
func()
原因:Python在函数内部如果对变量赋值,默认认为它是局部变量。在赋值前访问会报错。
解决:使用 global 或 nonlocal 明确声明,或避免在函数内重新赋值同名变量。
-
可变对象作为默认参数
错误示例:
def append_to_list(value, my_list=[]):
my_list.append(value)
return my_list
print(append_to_list(1)) # [1]
print(append_to_list(2)) # [1, 2] —— 期望是 [2]?
原因:默认参数在函数定义时只被评估一次,后续调用共享同一个列表。
解决:使用 None 作为默认值,函数内初始化:
def append_to_list(value, my_list=None):
if my_list is None:
my_list = []
my_list.append(value)
return my_list
-
列表推导式与生成器混淆
错误示例:
squares = (x**2 for x in range(5))
print(list(squares)) # [0, 1, 4, 9, 16]
print(list(squares)) # [] —— 生成器已耗尽
原因:生成器只能遍历一次。
解决:若需多次使用,转为列表,或重新创建生成器。
-
浅拷贝与深拷贝混淆
错误示例:
import copy
original = [[1, 2], [3, 4]]
shallow = copy.copy(original)
shallow[0][0] = 99
print(original) # [[99, 2], [3, 4]] —— 原列表也被修改
原因:浅拷贝只复制外层对象,内层仍为引用。
解决:需要完全独立副本时使用 copy.deepcopy()。
-
字符串拼接效率低
错误示例:
result = ""
for item in items:
result += str(item) # 每次都创建新字符串,效率低
原因:字符串不可变,+= 操作在循环中性能差。
解决:使用 ''.join(list_of_strings)。
-
异常处理不当
错误示例:
try:
risky_operation()
except: # 捕获所有异常,包括系统退出、键盘中断
pass
问题:过于宽泛的 except: 会掩盖错误,甚至阻止 Ctrl+C 退出。
解决:明确捕获具体异常,如 except ValueError:。
-
对可变对象的误解
错误示例:
a = [1, 2, 3]
b = a
b.append(4)
print(a) # [1, 2, 3, 4] —— a 也被修改
原因:b = a 是引用赋值,不是复制。
解决:使用 b = a.copy() 或 b = a[:] 创建副本。
-
is 与 == 混用
错误示例:
a = [1, 2]
b = [1, 2]
print(a == b) # True
print(a is b) # False —— 不是同一对象
说明:== 比较值,is 比较对象身份(内存地址)。
注意:小整数和短字符串有缓存,is 可能“巧合”为真,但不应依赖。
-
循环中修改列表
错误示例:
items = [1, 2, 3, 4, 5]
for item in items:
if item % 2 == 0:
items.remove(item) # 错误:边遍历边修改导致跳过元素
解决:使用列表推导式或反向遍历:
items = [x for x in items if x % 2 != 0]
-
忽略编码问题(尤其在文件操作)
错误示例:
with open('file.txt') as f: # 默认编码依赖系统
content = f.read()
问题:跨平台或含中文时可能报 UnicodeDecodeError。
解决:显式指定编码:
with open('file.txt', encoding='utf-8') as f:
content = f.read()
-
init.py 与包导入问题
问题:忘记创建 init.py 文件导致模块无法导入。
注意:Python 3.3+ 支持隐式命名空间包,但显式创建更清晰。 -
lambda 函数在循环中的绑定问题
错误示例:
functions = [lambda x: x * i for i in range(3)]
print([f(2) for f in functions]) # [4, 4, 4] —— 期望 [0, 2, 4]?
原因:i 是后期绑定,所有 lambda 共享最终的 i=2。
解决:使用默认参数捕获当前值:
functions = [lambda x, i=i: x * i for i in range(3)]
总结建议:
使用类型提示(def func(x: int) -> str:)提高可读性和工具支持。
使用 pylint、flake8、mypy 等静态检查工具提前发现问题。
多阅读官方文档和 PEP(如 PEP 8 风格指南)。

被折叠的 条评论
为什么被折叠?



