阿发聊测试 · 面试实战系列
一文速成!Python面试题,帮你全部搞定!
10大高频考点,小白vs大佬答法对比,面试不再慌
你好,我是阿发。
最近帮几个粉丝做面试辅导,发现大家在Python面试中总是踩同样的坑。比如被问到"列表和元组有什么区别",小白只会说"列表可以改,元组不能改",而大佬会从内存、性能、使用场景等多个维度分析。结果就是:同样的问题,小白拿60分,大佬拿90分。今天这篇文章,我把Python面试最高频的10个考点整理出来,每个题目都用"小白答法vs大佬答法"的形式对比,帮你快速掌握正确的答题思路。面试前看一遍,直接套用模板就能答出高分。
SECTION 01
考点1:可变类型vs不可变类型
这个问题几乎是Python面试的必考题,不管是初级还是高级岗位都会问。
面试题:列表和元组有什么区别?
小白答法:
列表用[],元组用()。列表可以改,元组不能改。
大佬答法:
从四个维度分析:
· 可变性:列表是可变类型(mutable),可以增删改元素;元组是不可变类型(immutable),创建后不能修改
· 内存占用:元组内存占用更小,因为不可变,Python可以提前分配固定内存
· 性能:元组访问速度更快,因为元素位置固定;列表需要维护动态数组,有额外开销
· 使用场景:列表适合需要频繁修改的数据集合;元组适合存储固定不变的数据,如配置参数、坐标点等
扩展:Python中的可变和不可变类型
· 不可变类型:int、float、str、tuple、bool、frozenset
· 可变类型:list、dict、set
易错点:不可变类型不是绝对不能变!比如元组里包含列表,列表是可变的,可以修改列表内容。但元组本身的元素(即列表对象的引用)不能变。
这个问题经常和可变/不可变类型一起考,很多人分不清浅拷贝和深拷贝。
面试题:什么是浅拷贝和深拷贝?区别是什么?
小白答法:
浅拷贝就是复制一下,深拷贝就是复制得更深一点。
大佬答法:
· 浅拷贝(shallow copy):只复制第一层对象,嵌套对象仍然共享引用。修改嵌套对象会影响原对象
· 深拷贝(deep copy):递归复制所有层次的对象,完全独立。修改任何部分都不会影响原对象
实现方式:
- 浅拷贝:copy.copy()、list[:]、dict.copy()
- 深拷贝:copy.deepcopy()
代码示例:直观理解
```python
import copy
original = [1, [2, 3]]
# 浅拷贝
shallow = copy.copy(original)
shallow[1][0] = 99
print(original) # [1, [99, 3]] # 原对象被修改了!
# 深拷贝
original = [1, [2, 3]]
deep = copy.deepcopy(original)
deep[1][0] = 99
print(original) # [1, [2, 3]] # 原对象不受影响
```
这个问题是Python面试的进阶题,高级岗位必问。很多人对GIL的理解都有误区。
面试题:什么是GIL?它对Python多线程有什么影响?
小白答法:
GIL就是一个锁,让Python只能用一个线程运行,所以Python多线程没用。
大佬答法:
GIL(Global Interpreter Lock)是CPython解释器的全局锁,同一时刻只允许一个线程执行Python字节码。
影响分析:
· CPU密集型任务:多线程不能提升性能,因为GIL限制了并行执行,反而有线程切换开销
· IO密集型任务:多线程有效,因为等待IO时GIL会释放,其他线程可以执行
· 解决方案:CPU密集型用多进程(multiprocessing),绕过GIL;IO密集型用多线程或异步IO
注意:GIL是CPython的实现细节,Jython、IronPython等其他实现没有GIL。
面试加分点:Python 3.2+引入了新的GIL释放机制,IO等待时会立即释放GIL;Python 3.10+进一步优化了GIL,减少了锁竞争。但本质上,CPU密集型任务仍然推荐用多进程。
SECTION 04
考点4:*args和**kwargs
这是Python的核心语法,面试中经常考,也是实际工作中非常实用的技巧。
面试题:*args和**kwargs是什么?有什么区别?
小白答法:
就是用来传参数的,一个是*,一个是**。
大佬答法:
· *args:接收任意数量的位置参数(positional arguments),打包成一个元组
· **kwargs:接收任意数量的关键字参数(keyword arguments),打包成一个字典
使用场景:
1. 函数定义时:让函数接受可变数量的参数,提高灵活性
2. 函数调用时:解包参数,把列表/元组/字典传给函数
代码示例:定义和调用
```python
# 定义时:接收可变参数
def print_args(*args, **kwargs):
print('位置参数:', args) # 元组
print('关键字参数:', kwargs) # 字典
print_args(1, 2, name='阿发', age=18)
# 输出:
# 位置参数: (1, 2)
# 关键字参数: {'name': '阿发', 'age': 18}
# 调用时:解包参数
def add(a, b, c):
return a + b + c
nums = [1, 2, 3]
print(add(*nums)) # 6,等价于add(1, 2, 3)
params = {'a': 1, 'b': 2, 'c': 3}
print(add(**params)) # 6,等价于add(a=1, b=2, c=3)
```
SECTION 05
考点5:列表推导式vs生成器表达式
这是Python的语法糖,也是面试中常考的优化技巧。
面试题:列表推导式和生成器表达式有什么区别?什么时候用哪个?
小白答法:
列表推导式用[],生成器表达式用()。生成器好像更省内存?
大佬答法:
核心区别:
· 列表推导式:立即生成全部元素,返回一个列表。内存占用大,但可以多次访问、支持索引
· 生成器表达式:惰性生成元素,返回一个生成器对象。内存占用极小(只存生成逻辑),只能迭代一次
选择策略:
· 需要多次访问元素、需要索引操作 → 用列表推导式
· 数据量大、只需要迭代一次 → 用生成器表达式
· 无限序列 → 只能用生成器
代码示例:对比内存占用
```python
# 列表推导式:立即生成100万个元素,占用大量内存
list_comp = [x for x in range(1000000)]
print(type(list_comp)) #
# 生成器表达式:只生成一个生成器对象,几乎不占内存
gen_expr = (x for x in range(1000000))
print(type(gen_expr)) #
# 生成器只能迭代一次
for num in gen_expr:
if num > 5:
break
for num in gen_expr: # 第二次迭代是空的!
print(num) # 不会输出任何内容
```
迭代器和生成器是Python的进阶概念,也是面试中区分能力的关键问题。
面试题:什么是迭代器?什么是生成器?它们之间是什么关系?
小白答法:
迭代器就是可以迭代的东西,生成器就是生成数据的。
大佬答法:
· 迭代器(Iterator):实现了__iter__和__next__方法的对象。调用next()返回下一个元素,没有元素时抛出StopIteration异常
· 生成器(Generator):一种特殊的迭代器,用yield关键字定义。每次遇到yield返回一个值,下次从yield处继续执行
关系:
生成器是迭代器的子集,所有生成器都是迭代器,但迭代器不一定是生成器
创建方式:
迭代器:用iter()函数或自定义类实现__iter__和__next__
生成器:生成器表达式或yield函数
代码示例:自定义迭代器和生成器
```python
# 自定义迭代器
class MyIterator:
def __init__(self, max_num):
self.max_num = max_num
self.current = 0
def __iter__(self):
return self
def __next__(self):
if self.current >= self.max_num:
raise StopIteration
self.current += 1
return self.current
# 生成器函数
def my_generator(max_num):
current = 0
while current < max_num:
current += 1
yield current # 暂停执行,返回值
# 使用
for num in MyIterator(3):
print(num) # 1, 2, 3
for num in my_generator(3):
print(num) # 1, 2, 3
```
SECTION 07
考点7:上下文管理器与with语句
with语句是Python的优雅语法,面试中经常考它的实现原理。
面试题:with语句的原理是什么?怎么实现自定义上下文管理器?
小白答法:
with语句用来打开文件,不用手动关闭。
大佬答法:
with语句的原理是上下文管理器协议,对象需要实现__enter__和__exit__两个方法:
· __enter__:进入with块时调用,返回值赋给as后面的变量
· __exit__:退出with块时调用,负责清理资源(如关闭文件)
即使with块中发生异常,__exit__也会被调用,确保资源被正确释放。
实现方式:
1. 自定义类实现__enter__和__exit__方法
2. 使用contextlib.contextmanager装饰器
代码示例:两种实现方式
```python
# 方式1:自定义类
class MyFile:
def __init__(self, filename, mode):
self.filename = filename
self.mode = mode
def __enter__(self):
self.file = open(self.filename, self.mode)
return self.file
def __exit__(self, exc_type, exc_val, exc_tb):
self.file.close()
# 方式2:contextmanager装饰器
from contextlib import contextmanager
@contextmanager
def my_file(filename, mode):
file = open(filename, mode)
try:
yield file # 返回值给as变量
finally:
file.close()
# 使用
with my_file('test.txt', 'w') as f:
f.write('hello')
```
SECTION 08
考点8:类属性vs实例属性与MRO
面向对象是Python面试的重点,类属性和实例属性的区别,以及MRO方法解析顺序是高频考点。
面试题:类属性和实例属性有什么区别?
小白答法:
类属性是类里面的属性,实例属性是实例里面的属性。
大佬答法:
· 类属性(Class Attribute):定义在类级别,所有实例共享。通过类名或实例访问,修改类属性会影响所有实例
· 实例属性(Instance Attribute):定义在__init__方法中,每个实例独有。只能通过实例访问,修改不影响其他实例
查找顺序:先查找实例属性,再查找类属性。如果实例没有该属性,会使用类属性的值。但如果给实例赋值同名属性,会创建实例属性,屏蔽类属性。
面试题:什么是MRO?Python如何处理多重继承?
大佬答法:
MRO(Method Resolution Order)是方法解析顺序,即当调用一个方法时,Python查找该方法的顺序。
Python 3使用C3线性化算法计算MRO,遵循以下原则:
1. 子类优先于父类
2. 多个父类按照声明顺序查找
3. 保证每个类只被访问一次
可以通过__mro__属性或mro()方法查看MRO。
内存管理是Python面试的进阶题,考察对Python底层机制的理解。
面试题:Python的内存管理机制是什么?垃圾回收是怎么实现的?
小白答法:
Python有垃圾回收,不用手动管理内存。
大佬答法:
Python的内存管理包含三个核心机制:
· 引用计数:每个对象维护一个引用计数器,引用+1时计数器+1,引用-1时计数器-1。当计数器为0时,对象立即被回收
· 标记清除:解决循环引用问题。定期扫描所有对象,标记可达对象,清除不可达对象
· 分代回收:基于"年轻对象更容易死亡"的假设,将对象分为三代(0、1、2)。新创建的对象属于第0代,存活越久的对象进入更高代。低代对象扫描频率更高
循环引用问题:引用计数无法回收相互引用的对象(如a.b = b, b.a = a),这时候需要标记清除来处理。
面试加分点:可以提到sys.getrefcount()查看引用计数,gc模块手动触发垃圾回收,以及__del__方法可能导致的问题(循环引用时__del__会阻止对象被回收)。
最后,整理一下面试中最常被问到的问题,方便你快速复习。
· Q1:Python是编译型还是解释型语言?
Python是解释型语言,但有编译过程。.py文件先编译成.pyc字节码,再由解释器执行。
· Q2:Python 2和Python 3的区别?
print从语句变成函数;Unicode默认;除法行为不同;xrange被移除;迭代器协议统一。
· Q3:什么是鸭子类型?
关注对象能做什么,而不是对象是什么类型。比如只要实现了__iter__和__next__就是迭代器。
· Q4:lambda函数的特点?
匿名函数,只能有一个表达式,返回表达式结果。适合简单操作,不适合复杂逻辑。
· Q5:sort和sorted的区别?
sort是列表方法,原地排序,返回None;sorted是内置函数,返回新列表,不修改原列表。
· Q6:is和==的区别?
is判断对象是否为同一个(内存地址相同);==判断对象的值是否相等。
· Q7:什么是闭包?
内部函数引用了外部函数的变量,形成闭包。闭包可以保留外部函数的变量状态。
· Q8:装饰器的本质是什么?
装饰器是接收函数作为参数并返回新函数的函数。@是语法糖,等价于func = decorator(func)。
· Q9:进程和线程的区别?
进程是资源分配的基本单位,线程是CPU调度的基本单位。进程间通信开销大,线程间共享内存。
· Q10:什么是协程?
协程是用户态的轻量级线程,由程序自身控制调度。Python中用async/await实现。
最后
Python面试题千千万,但高频考点就那么几个。今天整理的这10个考点,覆盖了从基础到进阶的核心内容。记住"小白答法vs大佬答法"的对比模式,面试时从多个维度分析问题,就能答出高分。建议把这篇文章收藏起来,面试前花半小时快速过一遍,效果立竿见影。
关于Python面试、测试进阶、AI测试转型等问题,都可以通过公众号菜单栏添加我微信 testafa 私信交流。需要面试资料也可以私信!