1. 关于 Python 中 list 和 tuple 的说法,正确的是?
A. list 不可变,tuple 可变
B. list 和 tuple 都可变
C. list 可变,tuple 不可变
D. list 和 tuple 都不可变
正确答案: C
详细解析:
list 是可变序列,支持增删改操作,例如 append()、remove()、索引赋值等。
tuple 是不可变序列,创建后元素不能被重新赋值、删除或新增。
例如:
a =[1,2,3]
a[0]=100# 合法
b =(1,2,3)
# b[0] = 100 # 会报错
面试中这道题往往会继续追问:
●为什么 tuple 更适合作为字典键的一部分?
●为什么 tuple 在某些场景下更节省内存?
2. Python 中 is 和 == 的区别是?
A. 两者都比较值
B. is 比较对象标识,== 比较值
C. is 比较值,== 比较内存地址
D. 两者都比较对象地址
正确答案: B
详细解析:
== 用于比较两个对象的值是否相等;is 用于比较两个变量是否引用同一个对象。
例如:
a =[1,2]
b =[1,2]
print(a == b)# True
print(a is b)# False
虽然 a 和 b 内容相同,但它们不是同一个对象。
面试中一定要特别记住:判断是否为 None 时,推荐使用 is,例如:
if x isNone:
pass
3. 以下哪个是 Python 中的不可变对象?
A. list
B. dict
C. set
D. str
正确答案: D
详细解析:
●Python 中常见不可变对象有:int
●float
●str
●tuple
●bool
可变对象包括:
●list
●dict
●set
字符串一旦创建,内容不能原地修改。例如:
s ="abc"
# s[0] = "x" # 报错
s ="xbc"# 这是重新绑定,不是修改原对象
4. 执行下面代码后,输出结果是什么?
a =[1,2,3]
b = a
b.append(4)
print(a)
A. [1, 2, 3]
B. [1, 2, 3, 4]
C. [4, 1, 2, 3]
D. 报错
正确答案: B
详细解析:
b = a 并没有创建新列表,而是让 b 和 a 指向同一个列表对象。
所以对 b 执行 append(4),本质上也是在修改 a 指向的那个对象。
这道题本质考查的是:
●Python 变量保存的是对象引用
●可变对象的共享引用问题
这是浅拷贝、深拷贝题型的基础。
5. 下列哪种方式适合高效拼接大量字符串?
A. 使用 + 循环拼接
B. 使用 join()
C. 使用 append()
D. 使用 update()
正确答案: B
详细解析:
字符串在 Python 中是不可变对象。
如果使用 + 在循环中不断拼接,每次都会产生新的字符串对象,效率较低。
''.join(iterable) 会一次性完成拼接,性能更好。
例如:
words =["I","love","Python"]
result =" ".join(words)
append() 是列表方法,update() 是字典方法,因此不适合字符串拼接。
6. 关于 Python 函数参数 *args 的说法,正确的是?
A. 接收任意数量的关键字参数,类型是字典
B. 接收任意数量的位置参数,类型是元组
C. 接收任意数量的位置参数,类型是列表
D. 只能接收一个参数
正确答案: B
详细解析:
*args 用来接收任意数量的位置参数,最终会以元组的形式保存。
例如:
def func(*args):
print(args)
func(1,2,3)
输出:
(1,2,3)
与之对应:
●*args:位置参数,元组
●**kwargs:关键字参数,字典
7. 关于 **kwargs 的说法,正确的是?
A. 用于接收任意数量的关键字参数,类型是字典
B. 用于接收任意数量的位置参数,类型是元组
C. 只能接收字符串参数
D. 只能在类中使用
正确答案: A
详细解析:
**kwargs 用于接收任意数量的关键字参数,结果是一个字典。
例如:
def func(**kwargs):
print(kwargs)
func(name="Tom", age=18)
输出:
{'name':'Tom','age':18}
这是 Python 中非常常见的动态传参方式,装饰器、框架封装、通用函数中经常使用。
8. 下列关于浅拷贝和深拷贝的说法,正确的是?
A. 浅拷贝和深拷贝完全没有区别
B. 浅拷贝会递归复制所有层对象
C. 深拷贝只复制最外层对象
D. 深拷贝会递归复制所有层对象
正确答案: D
详细解析:
浅拷贝只复制最外层对象,内部嵌套对象仍共享引用。
深拷贝会递归复制所有层级对象,复制后彼此独立。常见方式:
●浅拷贝:copy.copy()
●深拷贝:copy.deepcopy()
例如二维列表:
import copy
a =[[1,2],[3,4]]
b = copy.copy(a)
c = copy.deepcopy(a)
如果修改 b[0][0],可能影响 a;
修改 c[0][0],通常不会影响 a。
9. 下列哪个关键字可以把普通函数变成生成器?
A. return
B. yield
C. break
D. pass
正确答案: B
详细解析:
只要函数体中包含 yield,这个函数就不再是普通函数,而是生成器函数。调用它时不会立即执行,而是返回一个生成器对象。
例如:
defgen():
yield1
yield2
生成器适合处理:
●大数据量
●惰性求值
●流式处理
10. 关于生成器和列表的区别,正确的是?
A. 列表比生成器更节省内存
B. 生成器支持随机索引访问
C. 生成器按需产生数据
D. 生成器可以无限次重复遍历且不消耗资源
正确答案: C
详细解析:
生成器最大的特点是“按需生成”,不会一次性把所有数据加载进内存,因此更节省空间。
而列表会立即生成所有元素。例如:
g =(x*x for x inrange(1000000))
这里不会一次性占用特别大的内存。
但生成器通常不支持索引访问,也不能像列表一样反复任意读取。
11. 下列哪个对象通常不是迭代器?
A. 生成器对象
B. 文件对象
C. 列表对象
D. map() 返回值
正确答案: C
详细解析:
列表是可迭代对象,但通常不是迭代器。
它能通过 iter() 返回一个迭代器,但本身不直接具备 __next__() 的逐个取值能力。
而以下对象通常是迭代器:
●生成器对象
●文件对象
●map() 返回对象
●filter() 返回对象
区分:
●可迭代对象:能被 for 遍历
●迭代器:能被 next() 调用
12. 关于 lambda 表达式的说法,正确的是?
A. 可以写多行复杂逻辑
B. 只能定义匿名类
C. 适合定义简单的一行函数
D. 只能用于数学运算
正确答案: C
详细解析:
lambda 用于定义匿名函数,语法简洁,适合简单场景。
例如:
f =lambda x: x +1
print(f(3))
常见使用场景:
●sorted(key=...)
●map()
●filter()
但如果逻辑复杂,建议使用 def,因为 lambda 只支持单表达式,过度使用会影响可读性。
13. 下列哪个选项最适合对列表元素进行筛选?
A. map()
B. filter()
C. reduce()
D. print()
正确答案: B
详细解析:
filter() 用于根据条件筛选元素。
例如:
nums =[1,2,3,4]
result =filter(lambda x: x >2, nums)
print(list(result))# [3, 4]
其他选项:
●map():映射处理
●reduce():归约累积
●print():输出
14. 下列关于列表推导式的说法,正确的是?
A. 不能带条件判断
B. 只能生成数字列表
C. 是一种简洁构造列表的方式
D. 性能一定比所有写法都差
正确答案: C
详细解析:
列表推导式是 Python 中非常常见、非常 Pythonic 的写法。例如:
squares =[x*x for x inrange(10)if x %2==0]
它支持:
●生成新列表
●条件过滤
●表达式变换
优点:
●语法简洁
●通常可读性较好
●常比手写 for + append 更自然
但如果嵌套太深,也会变得难读。
15. 以下关于默认参数的说法,正确的是?
A. 默认参数每次调用函数时都会重新创建
B. 默认参数中的可变对象不会共享
C. 默认参数在函数定义时就确定
D. 默认参数不能使用 None
正确答案: C
详细解析:
Python 中函数默认参数是在函数定义时计算一次,而不是每次调用时重新生成。
这也是为什么默认参数不建议直接使用可变对象。例如:
deffunc(a=[]):
a.append(1)
return a
多次调用 func() 会不断在同一个列表里追加内容。
正确写法通常是:
deffunc(a=None):
if a isNone:
a =[]
这类题在面试中非常高频。
16. Python 字典的底层主要基于什么实现?
A. 链表
B. 栈
C. 队列
D. 哈希表
正确答案: D
详细解析:
Python 的 dict 底层主要基于哈希表实现,因此查找、插入、删除在平均情况下时间复杂度是 O(1)。
字典的核心原理包括:
●键通过 hash() 计算哈希值
●根据哈希值快速定位槽位
●处理哈希冲突
这也是为什么字典查询通常比列表遍历快得多。
17. 为什么 Python 字典的键必须是可哈希对象?
A. 因为字典底层要计算键的哈希值
B. 因为字典键必须能排序
C. 因为字典键必须是数字
D. 因为字典键必须可变
正确答案: A
详细解析:
字典是哈希表结构,所以键必须能够计算出稳定的哈希值。
如果对象是可变的,它的状态变了,哈希值可能也会变化,就会破坏字典的查找结构。可作为字典键的常见类型:
●int
●str
●tuple(元素也必须可哈希)
不能作为字典键的常见类型:
●list
●dict
●set
18. 下列哪个选项可以正确捕获异常?
A. try-if
B. try-while
C. try-except
D. if-except
正确答案: C
详细解析:
Python 中使用 try-except 捕获异常。
基本语法:
try:
x =1/0
except ZeroDivisionError:
print("除零异常")
还可以配合:
●else:没有异常时执行
●finally:无论是否异常都执行
这是 Python 异常处理的标准结构。
19. 关于 finally 的作用,正确的是?
A. 只有发生异常时才执行
B. 只有没有异常时才执行
C. 一般用于释放资源,无论是否异常都会执行
D. 只能放在函数内部
正确答案: C
详细解析:
finally 中的代码通常都会执行,不论是否发生异常。
●因此它非常适合做资源清理工作,例如:关闭文件
●关闭数据库连接
●释放锁
例如:
try:
f =open("a.txt")
finally:
f.close()
不过在现代 Python 中,文件这类资源更推荐使用 with 管理。
20. with open(...) as f: 语句的主要作用是?
A. 提高循环速度
B. 自动管理资源
C. 自动创建类
D. 自动捕获所有异常
正确答案: B
详细解析:
with 语句用于上下文管理器,可以在代码块开始和结束时自动处理资源的申请与释放。
文件操作中最常见:
withopen("test.txt","r", encoding="utf-8")as f:
data = f.read()
即使发生异常,文件也会被正确关闭。
●底层依赖对象实现:__enter__()
●__exit__()
21. Python 面向对象的三大特性不包括以下哪一项?
A. 封装
B. 继承
C. 多态
D. 编译
正确答案: D
详细解析:
●Python 面向对象三大特性是:封装
●继承
●多态
“编译”不是面向对象特性,它属于程序执行或语言实现层面的概念。
面试中如果回答这题,最好顺带能解释:
●封装:隐藏细节,对外提供接口
●继承:提高代码复用
●多态:同一接口,不同实现
22. 在类的方法中,实例方法的第一个参数通常是?
A. cls
B. this
C. self
D. obj
正确答案: C
详细解析:
Python 中实例方法第一个参数通常写作 self,代表当前实例对象。
这是约定俗成的命名,不是强制语法关键字,但实际开发必须遵循这个规范。例如:
classPerson:
defsay(self):
print("hello")
类方法一般使用 cls,静态方法没有默认的实例或类参数。
23. @classmethod 修饰的方法,第一个参数通常是?
A. self
B. cls
C. args
D. kwargs
正确答案: B
详细解析:
类方法使用 @classmethod 修饰,第一个参数通常是 cls,表示当前类本身。
例如:
classA:
@classmethod
defshow(cls):
print(cls)
类方法常用于:
●操作类属性
●工厂方法
●替代构造器
与之对比:
●实例方法:第一个参数是 self
●静态方法:无默认参数
24. 关于 @staticmethod 的说法,正确的是?
A. 必须访问实例属性
B. 必须访问类属性
C. 不依赖实例和类状态
D. 只能在继承中使用
正确答案: C
详细解析:
静态方法使用 @staticmethod 修饰,它本质上放在类的命名空间下,但不依赖实例对象或类对象的状态。
例如:
classMathTool:
@staticmethod
defadd(a, b):
return a + b
适合放一些逻辑上与类有关、但并不操作实例或类状态的工具函数。
25. Python 中多继承可能引发的问题主要是?
A. 无法定义类
B. 方法解析顺序复杂
C. 不能创建对象
D. 无法调用父类方法
正确答案: B
详细解析:
●Python 支持多继承,但多继承可能带来:方法名冲突
●继承结构复杂
●MRO(方法解析顺序)难以理解
例如:
classA:pass
classB:pass
classC(A, B):pass
当多个父类存在同名方法时,Python 需要按照 MRO 决定调用顺序。
因此实际开发中,多继承要谨慎使用。
26. Python 中 MRO 的含义是?
A. 内存回收顺序
B. 模块导入顺序
C. 方法解析顺序
D. 变量初始化顺序
正确答案: C
详细解析:
MRO 全称是 Method Resolution Order,即方法解析顺序。
在继承关系中,尤其是多继承场景下,Python 会按照 MRO 查找方法。可通过以下方式查看:
ClassName.mro()
或者:
ClassName.__mro__
面试中如果能再补充一句“Python 新式类采用 C3 线性化算法”,会更显专业。
27. Python 的垃圾回收机制主要不包括以下哪项?
A. 引用计数
B. 分代回收
C. 循环引用检测
D. 手动内存地址偏移
正确答案: D
详细解析:
●Python 的垃圾回收机制主要包括:引用计数
●分代回收
●循环引用检测
“手动内存地址偏移”是底层语言如 C 中更相关的概念,不属于 Python 垃圾回收机制。
这道题经常用来区分是否真正理解 Python 内存管理,而不是只会背“引用计数”。
28. 关于 GIL 的说法,正确的是?
A. GIL 使 Python 多线程在 CPU 密集型任务中一定更快
B. GIL 是数据库锁
C. 在 CPython 中,同一时刻只有一个线程执行 Python 字节码
D. GIL 只影响多进程,不影响多线程
正确答案: C
详细解析:
GIL 是全局解释器锁,主要存在于 CPython 中。
它的核心影响是:同一时刻只能有一个线程执行 Python 字节码。因此:
●对于 CPU 密集型任务,多线程通常难以发挥真正并行优势
●对于 I/O 密集型任务,多线程仍然有价值,因为阻塞等待时可以切换线程
这题是 Python 面试高频题,不能简单说“Python 多线程没用”,那是不严谨的。
29. 下列哪种方案通常更适合处理 CPU 密集型任务?
A. 多线程
B. 多进程
C. 仅使用 print()
D. 仅使用 input()
正确答案: B
详细解析:
●CPU 密集型任务主要消耗处理器计算资源,例如:图像处理
●数据计算
●数学建模
●编码解码
由于 CPython 存在 GIL,多线程在 CPU 密集型场景下往往无法真正并行。
而多进程每个进程有独立解释器和内存空间,可以绕过 GIL,更适合这类任务。
30. 下列哪种场景最适合使用协程(async/await)?
A. 大量网络请求并发处理
B. 大规模矩阵乘法
C. 大量图片像素级 CPU 运算
D. 纯数学公式推导
正确答案: A
详细解析:
协程最适合 高并发 I/O 场景,例如:
●网络爬虫
●异步接口服务
●批量 HTTP 请求
●消息处理
因为这些任务大量时间消耗在“等待”上,而不是一直占用 CPU。
使用 async/await 可以提升 I/O 并发能力,减少线程切换开销。
但对于纯 CPU 计算任务,协程通常不如多进程更合适。
复习建议
如果你要准备 Python 面试,建议把题目按下面几类来记:
一、基础语法与数据结构
重点看:
●list、tuple
●str
●dict
●可变与不可变对象
●is 和 ==
二、函数与高级特性
重点看:
●*args、**kwargs
●默认参数
●lambda
●列表推导式
●生成器、迭代器
三、面向对象
重点看:
●封装、继承、多态
●实例方法、类方法、静态方法
●多继承与 MRO
四、异常与资源管理
重点看:
●try-except-finally
●with
●上下文管理器
五、并发与底层机制
重点看:
●GIL
●多线程、多进程、协程
●垃圾回收机制