Python 新手常踩的三个坑:可变默认参数、浅拷贝陷阱与异常处理
Python 语法简洁、入门门槛低,但有些设计细节对新手并不友好。我在学习 Python 的过程中踩过不少坑,今天把其中最常见的三个整理出来:可变默认参数、浅拷贝陷阱、异常处理不当。每个坑都附上出错示例和正确写法,希望能帮新手少走弯路。
坑一:用可变对象做默认参数
先看一段很"自然"的代码:
def add_item(item, items=[]):
items.append(item)
return items
print(add_item("苹果")) # ['苹果']
print(add_item("香蕉")) # ['苹果', '香蕉']
第二次调用时明明只传了"香蕉",结果里却多了一个"苹果"。这是因为函数的默认参数只在函数定义时求值一次:那个 [] 对象在整个程序运行期间只有一份,所有没传 items 的调用共享的是同一个列表,append 的结果会一直累积。
正确写法是用 None 做哨兵值,在函数内部新建列表:
def add_item(item, items=None):
if items is None:
items = []
items.append(item)
return items
print(add_item("苹果")) # ['苹果']
print(add_item("香蕉")) # ['香蕉']
记住一条规则:默认参数永远只用不可变对象(None、数字、字符串、元组),可变对象一律在函数体内创建。
坑二:浅拷贝"复制"了嵌套结构
import copy
matrix = [[1, 2], [3, 4]]
clone = copy.copy(matrix) # 浅拷贝
clone[0].append(99)
print(matrix) # [[1, 2, 99], [3, 4]]
我们只想改副本,结果原数据也被改了。原因是浅拷贝只复制最外层容器,内层的子列表依然是同一个对象的引用,改子列表等于直接改原数据。
如果数据结构是嵌套的,请用深拷贝:
clone = copy.deepcopy(matrix)
clone[0].append(99)
print(matrix) # [[1, 2], [3, 4]]
原数据纹丝不动。只有确认数据结构只有一层时,list.copy() 或切片 [:] 才是安全的;嵌套结构一律 deepcopy。
坑三:异常处理"一锅端"
try:
num = int(input("请输入数字:"))
result = 100 / num
data = open("config.txt").read()
except Exception as e:
print("出错了:", e)
裸的 except Exception 会吞掉所有异常:用户输错、除零、文件不存在,全挤进同一个 except。出了问题很难定位,还可能把本该中断程序的严重错误也悄悄放过,留下隐患。
正确做法是捕获越具体越好,不同异常分开处理:
try:
num = int(input("请输入数字:"))
except ValueError:
print("请输入一个合法的整数")
raise
try:
result = 100 / num
except ZeroDivisionError:
print("除数不能为零")
try:
with open("config.txt") as f:
data = f.read()
except FileNotFoundError:
print("配置文件不存在,请检查路径")
只在你真正知道该如何处理时才捕获异常,否则就让它抛出来——"一锅端"看似省事,实则是把调试成本留给了未来的自己。
小结
这三个坑的本质都是"想当然":想当然地认为默认参数每次都会新建、想当然地认为复制就是独立的、想当然地认为捕获所有异常最省事。写 Python 时多问自己一句"这段代码到底引用了谁",很多坑就能提前避开。
- 点赞
- 收藏
- 关注作者
评论(0)