查看: 111|回复: 3

Python面试必避20个代码坑:可变默认参数、闭包延迟绑定与GIL详解

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
对于刚接触Python的开发者来说,基础语法看似简单,但实际编码中隐藏着大量“看着对、实则错”的隐性机制。这些坑不仅让线上代码崩溃,更是面试中的高频考题。下面整理了20个最常出现的Python陷阱,每个都附有错误示例、原因分析和正确写法,覆盖默认参数、深浅拷贝、循环变量泄露、整数缓存、GIL(全局解释器锁)、异常捕获、文件操作等核心知识点。
  1. 1. 默认参数为可变对象
  2. 错误写法:
  3. def func(arr=[]):
  4.     arr.append(1)
  5.     print(arr)
  6. func()
  7. func()  # 输出 [1] [1, 1],列表不断累加
  8. 原因:默认参数在函数定义时仅创建一次,后续调用复用同一对象。
  9. 正确写法:
  10. def func(arr=None):
  11.     if arr is None:
  12.         arr = []
  13.     arr.append(1)
  14.     print(arr)
复制代码
  1. 2. for循环变量泄露
  2. 错误示例:
  3. for i in range(3):
  4.     pass
  5. print(i)  # 输出2,循环结束后i依然存在
  6. 原因:Python的for循环不会创建独立作用域,循环变量会泄露到外部命名空间。
  7. 解决:避免外部复用同名变量,或将逻辑抽取到单独函数中。
复制代码
  1. 3. 遍历列表时删除元素
  2. 错误写法:
  3. lst = [1, 2, 3, 4]
  4. for i in lst:
  5.     if i % 2 == 0:
  6.         lst.remove(i)
  7. print(lst)  # 可能漏删或索引错乱
  8. 原因:遍历过程中列表长度变化,导致后续元素索引移位。
  9. 正确写法:用列表推导式创建新列表:
  10. lst = [x for x in lst if x % 2 != 0]
复制代码
  1. 4. == 与 is 混用
  2. 规则:== 比较值是否相等,is 比较内存地址是否相同。
  3. 陷阱:小整数(-5~256)和短字符串可能被缓存,导致 is 结果与预期不符。
  4. 建议:值比较用==,判断None或单例时用is。
复制代码
  1. 5. 整数缓存范围(-5~256)
  2. 交互式环境示例:
  3. a = 256; b = 256; print(a is b)  # True
  4. c = 257; d = 257; print(c is d)  # False(超出缓存范围)
  5. 注意:在.py文件中因编译优化行为可能略有不同,但仍不建议依赖is判断整数值。
复制代码
  1. 6. 字符串拼接使用大量 +
  2. 错误:'a' + 'b' + 'c' ... 产生大量临时字符串对象。
  3. 原因:字符串不可变,每次拼接都创建新对象。
  4. 正确做法:使用 ''.join(iterable) 方法。
复制代码
  1. 7. 字典直接取值导致KeyError
  2. 错误:d = {'name': 'Tom'}; print(d['age'])  # 抛出KeyError
  3. 正确:d.get('age', 18)  # 返回默认值18,不会崩溃
复制代码
  1. 8. 浅拷贝导致嵌套列表联动
  2. 示例:
  3. a = [[1, 2], 3]
  4. b = list(a)
  5. b[0][0] = 99
  6. print(a)  # [[99, 2], 3] 原数据被修改
  7. 原因:只拷贝外层对象,内层列表仍为引用。
  8. 解决:对嵌套结构使用 copy.deepcopy()。
复制代码
  1. 9. 裸 except 捕获所有异常
  2. 错误:try: 1/0 except: pass  # 隐藏了ZeroDivisionError
  3. 危害:导致排错困难,线上可能吞掉关键错误。
  4. 正确:永远捕获具体异常类型,如 except ValueError:。
复制代码
  1. 10. 文件 open 后不关闭
  2. 资源泄露,可能导致句柄耗尽、文件无法删除。
  3. 正确:使用 with open('file.txt') as f: 上下文管理器自动关闭。
复制代码
  1. 11. 全局变量修改未声明 global
  2. num = 10
  3. def f():
  4.     num = 20  # 创建局部变量,不修改全局
  5. f()
  6. print(num)  # 10
  7. 如需修改全局变量,函数内必须加 global num。
复制代码
  1. 12. 闭包延迟绑定(面试高频)
  2. 示例:
  3. funcs = []
  4. for i in range(3):
  5.     def f():
  6.         print(i)
  7.     funcs.append(f)
  8. funcs[0]()  # 输出2,不是0
  9. funcs[1]()  # 输出2
  10. 原因:闭包捕获的是变量i的引用,循环结束后i为2。
  11. 解决:使用默认参数立即绑定:
  12. def f(i=i):
  13.     print(i)
复制代码
  1. 13. True/False 本质是 1/0
  2. print(True == 1)  # True
  3. 判断布尔值时不要与数字混用,避免逻辑混淆。
复制代码
  1. 14. if 多条件连续赋值错误
  2. 错误:if a == 1 or 2:  # 永远成立,因为2为真
  3. 原因:误以为 or 需要完整条件,实际上2被视为布尔值True。
  4. 正确:if a == 1 or a == 2:
复制代码
  1. 15. 空列表/字典的布尔判断
  2. 空列表[]、空字典{}、空字符串''、0、None 在条件判断中均为False。
  3. 容易引起逻辑误判,例如:if not my_list: 时不要假设变量非空。
复制代码
  1. 16. 递归深度溢出
  2. Python默认递归深度约1000,超出则抛出RecursionError。
  3. 优先考虑迭代实现;若必须递归,可设置 sys.setrecursionlimit(),但风险较大。
复制代码
  1. 17. time.sleep 阻塞协程
  2. 在asyncio协程中使用 time.sleep(n) 会阻塞整个事件循环。
  3. 正确:await asyncio.sleep(n)
复制代码
  1. 18. 多线程高估效率(GIL坑)
  2. Python的GIL导致同一时间只有一个线程执行字节码,CPU密集型任务多线程反而更慢。
  3. 正确:CPU密集任务使用 multiprocessing 多进程。
复制代码
  1. 19. 函数返回多个值默认元组
  2. def test(): return 1, 2
  3. res = test()
  4. print(type(res))  # tuple
  5. 解包时需注意元素个数匹配,否则引发ValueError。
复制代码
  1. 20. 编码不指定导致乱码
  2. Windows默认GBK,Linux默认UTF-8,跨平台时文件读写可能乱码。
  3. 强制指定编码:
  4. with open('file.txt', encoding='utf-8') as f:
复制代码

以上20个陷阱是Python新手最常遇到的雷区,覆盖了从基础语法到并发编程的多个层面。理解其背后的本质——可变对象缓存、作用域规则、对象模型等——比死记硬背更重要。面试中这些知识点也反复出现,建议结合代码练习彻底吃透。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python面试必避20个代码坑:可变默认参数、闭包延迟绑定与GIL详解

整理得非常全面,尤其闭包延迟绑定和GIL那两点确实是面试高频雷区,我面试时就被问过类似延迟绑定的例子,当时没想通为什么输出全是2。楼主把可变默认参数、列表遍历删除这些日常最容易踩的坑都列出来了,还配上原因和正确写法,对新手特别友好。感谢分享,收藏了慢慢对照查漏补缺。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python面试必避20个代码坑:可变默认参数、闭包延迟绑定与GIL详解

感谢楼主这么用心地整理!这20个坑真的个个经典,特别是可变默认参数和闭包延迟绑定,我自己面试的时候就被问过好多次,第一次写的时候也踩过。像第5点整数缓存,虽然平时不依赖is判断值,但知道了底层原理对理解Python对象模型很有帮助。 另外第12点闭包的那个默认参数小技巧,我之前一直没搞懂为什么加个 `i=i` 就能解决问题,后来才意识到是函数定义时默认参数会被立即计算,相当于把当前循环变量的值固定下来了。这个思路在写循环回调时特别实用。 还有第18点GIL,很多人一开始以为Python多线程能并行加速,结果CPU密集型任务反而变慢了,这个坑确实容易让人怀疑人生😂。 再次感谢,已收藏,以后复习面试直接看你这篇就够了。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python面试必避20个代码坑:可变默认参数、闭包延迟绑定与GIL详解

楼主总结得很全面,这20个坑确实都是新手甚至老手容易踩的雷。尤其是可变默认参数和闭包延迟绑定,面试里几乎次次被问到。我补充一个点:第5条整数缓存范围在Python 3.8以后有些版本允许自定义,但日常写代码还是别依赖is判断整数值,用==最保险。第12条除了用默认参数,也可以用`functools.partial`绑定循环变量,不过默认参数方式最简洁。感谢分享,收藏了!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-28 13:56 , Processed in 0.029531 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部