初学者常犯的7个Python错误(以及正确的做法)
内容提要
Python程序看似正常却出错,多因假设与代码实际不符。常见七类问题:pip安装但导入失败(Python版本不同)、文件名遮蔽模块、输入类型错误、静默捕获异常、迭代时修改集合、误用原地方法返回值、zip()截断数据。排查时先检查解释器路径、模块来源、数据类型,并让异常可见,而非盲目重写代码。
延伸解读
排查思路:先验证环境,再怀疑代码
文章强调,许多看似莫名其妙的错误,根源在于环境或假设与代码实际不符。例如,pip安装成功但导入失败,往往是因为存在多个Python解释器,pip和脚本运行在不同的环境。此时应使用sys.executable和module.__file__来确认实际使用的解释器和模块来源,而不是盲目重装。这种“先验证环境,再怀疑代码”的排查思路,能快速定位问题,避免浪费时间。
数据边界处理:显式转换与异常可见
input()返回字符串,直接参与运算会出错,甚至产生“9”>“10”这类逻辑错误。文章建议在数据进入程序时显式转换类型,并捕获可能的ValueError。同时,捕获异常时不应静默忽略,否则会丢失错误线索。正确的做法是捕获特定异常并妥善处理,或记录异常信息后重新抛出,确保问题可见,便于后续排查。
迭代与修改:避免在遍历时改变集合
在遍历列表时直接删除元素,会导致跳过相邻元素或引发RuntimeError。这是因为修改操作影响了迭代器的索引。安全的做法是遍历副本或使用列表推导式创建新列表。这一原则同样适用于其他可变对象,理解迭代机制有助于避免此类隐蔽错误。
方法返回值陷阱:区分原地操作与返回新对象
list.sort()、append()等原地修改的方法返回None,若误将其赋值给变量,会导致变量变为None,后续操作报错。文章建议明确选择:需要修改原列表时单独调用方法,需要新列表时使用sorted()等返回新对象的函数。这一陷阱提醒开发者注意方法文档,避免因返回值假设错误而引入bug。
Q&A
为什么pip安装包后import仍然失败?
通常是因为系统中有多个Python解释器,pip安装到了其中一个,而你的脚本运行在另一个解释器下。解决方法是在虚拟环境中使用`python -m pip install`安装,并检查`sys.executable`确认解释器路径。
为什么我的json.py文件会导致import json出错?
因为你的文件名与标准库模块同名,Python在导入时会优先找到当前目录下的文件,导致标准库被遮蔽。解决方法是重命名文件,并删除可能存在的__pycache__缓存。
如何处理用户输入导致的类型错误?
input()返回的是字符串,直接进行数学运算会出错。应在输入边界显式转换类型,例如使用int(input()),并捕获ValueError异常以处理无效输入。
为什么捕获异常后程序没有报错但结果不对?
因为使用了`except Exception: pass`,这会静默吞掉异常,导致错误被忽略。正确做法是捕获特定异常并处理,或者记录异常并重新抛出,以保留错误信息。
在迭代列表时删除元素为什么会跳过一些元素?
因为删除元素后,列表索引会前移,而循环索引继续递增,导致被删除元素的下一个元素被跳过。解决方法是遍历列表的副本,或者使用列表推导式创建新列表。
为什么numbers.sort()返回None?
因为list.sort()是原地排序,返回None。如果将其赋值给变量,变量会变成None。应直接调用numbers.sort(),或使用sorted(numbers)返回新列表。
zip()函数为什么没有警告就丢弃了多余的数据?
因为zip()默认在最短的可迭代对象结束时停止,多余的元素会被静默丢弃。如果希望长度不一致时抛出错误,可以使用zip(..., strict=True)(Python 3.10+)。