Python常见面试题解析_高频问题解题思路

1次阅读

python面试重在理解特性、设计与调试思维,高频题聚焦可变默认参数陷阱、is/==区别、生成器实现及gil真实场景应用。

Python常见面试题解析_高频问题解题思路

Python面试题不考死记硬背,重在考察对语言特性的理解、代码设计意识和调试思维。高频题看似简单,但容易在边界处理、性能意识或底层逻辑上暴露短板。下面聚焦几类真题,讲清楚“为什么这么答”和“怎么想到的”。

一、可变对象作为函数默认参数的陷阱

题目常以如下代码开场:

def add_item(item, lst=[]):     lst.append(item)     return lst <p>print(add_item(1))  # [1] print(add_item(2))  # [1, 2] ← 意外!

问题本质不是“怎么改”,而是“为什么错”。关键点在于:默认参数在函数定义时只初始化一次,可变对象(如 list、dict)会被所有后续调用共享。第二次调用时,用的仍是第一次创建的那个 list。

  • ✅ 正确写法:用 None 作默认值,在函数体内初始化
  • ✅ 理解延伸:不可变对象(如 int、str、None)没这问题,因为赋值会绑定新对象;而 append 是原地修改
  • ✅ 验证技巧:打印 id(lst) 就能看到两次调用是否指向同一内存地址

二、“is” 和 “==” 的区别不能只背定义

很多候选人能说出“is 比较身份,== 比较值”,但遇到实际题仍出错,比如:

立即学习Python免费学习笔记(深入)”;

a = 257 b = 257 print(a is b)  # False?还是 True?

答案是 False(在交互式环境或普通脚本中)。原因在于:CPython 对小整数(-5 到 256)做了缓存优化,超出范围后每次字面量都会新建对象。所以 257 is 257 在某些上下文(如单行语句)可能为 True,但不可依赖。

  • ✅ 原则:判断相等用 ==,判断是否为同一对象(如单例、None 检查)才用 is
  • ✅ 特殊安全用法:if x is None 而不是 if x == None
  • ✅ 陷阱提醒:“字符串驻留”也有类似行为(如 ‘hello’ is ‘hello’ 通常为 True),但受编译器优化影响,不保证跨环境一致

三、生成器与迭代器的现场手写能力

面试官常让手写一个带状态的生成器,例如:“实现一个 countdown 类,支持 for 循环,且能多次遍历”。错误答案常写成返回 list,或误用 __iter__ + yield 混搭。

  • ✅ 正确思路:生成器函数(含 yield)每次调用都返回新生成器对象,天然支持多次遍历
  • ✅ 关键细节:不要在类里直接写 yield,而应定义一个生成器方法,再在 __iter__ 中调用它
  • ✅ 示例核心:

class Countdown:     def __init__(self, start):         self.start = start <pre class='brush:python;toolbar:false;'>def __iter__(self):     n = self.start     while n > 0:         yield n         n -= 1

这样每次 for c in Countdown(3): 都获得独立迭代器,互不影响。

四、GIL 与线程/多进程的真实适用场景

被问“Python 多线程有用吗”,答“没用因为 GIL”是减分项。GIL 只限制同一时刻只有一个线程执行 Python 字节码,但它不影响系统调用(如文件读写、网络请求、time.sleep)期间的线程切换。

  • ✅ CPU 密集型任务:用 multiprocessing,避免 GIL 竞争
  • ✅ IO 密集型任务:threading 完全可用,甚至更轻量(如并发请求多个 API)
  • ✅ 实用建议:用 concurrent.futures 模块统一接口,ThreadPoolExecutor / ProcessPoolExecutor 切换成本低
  • ✅ 补充事实:C 扩展(如 numpy 计算、正则匹配)在执行时会释放 GIL,此时多线程也能提升 CPU 利用率

text=ZqhQzanResources