Python 面试题
使用建议:
- 先只看问题,尝试自己口述回答。
- 再看标准答法,补齐关键词。
- 最后结合你自己的项目经验补一个例子,这样回答会更像真实面试而不是背书。
一、基础认知与语言特性
解释型语言 Python 和编译型语言有什么区别?
Python 通常被称为解释型语言,代码先编译成字节码,再由解释器逐步执行; 编译型语言通常会先整体编译成机器码后再运行。 解释型语言开发效率高、跨平台好,但运行时通常比纯编译型语言慢; 编译型语言通常执行效率更高,但编译和调试成本可能更大。
Python3 中 is 和 == 有什么区别?
== 比较的是两个对象的值是否相等。
is 比较的是两个对象是不是同一个对象,也就是内存地址是否相同。
比如判断 None 时推荐使用 is None,而不是 == None。
Python 中 read、readline、readlines 有哪些区别?
read():- 一次读取整个文件,或者读取指定字节数。
readline():- 一次读取一行。
readlines():- 一次读取所有行,返回列表。
大文件场景不建议直接用 read() 或 readlines(),更推荐逐行遍历文件对象。
什么是 Python 面向对象中的继承特点?
继承就是子类复用父类的属性和方法,并可以扩展或重写父类行为。 它的核心特点是代码复用、层次化建模和多态支持。 Python 支持单继承,也支持多重继承。
Python 中 any() 和 all() 方法有什么作用?
any(iterable):- 可迭代对象中只要有一个元素为真,就返回
True。
- 可迭代对象中只要有一个元素为真,就返回
all(iterable):- 可迭代对象中所有元素都为真,才返回
True。
- 可迭代对象中所有元素都为真,才返回
常用于条件批量判断。
nums = [1, 0, 3]
any(nums) # True
all(nums) # False
说明 Python3 中装饰器的用法
装饰器本质上是一个函数,用来在不修改原函数代码的前提下,为函数增加额外功能。 常见用途有日志、权限校验、性能统计、缓存等。
def log_decorator(func):
def wrapper(*args, **kwargs):
print("before")
result = func(*args, **kwargs)
print("after")
return result
return wrapper
@log_decorator
def hello():
print("hello")
说明 Python3 中 yield 的用法
yield 用于定义生成器函数。
函数执行到 yield 时会暂停并返回当前值,下次继续从暂停位置往下执行。
它适合处理大数据、惰性计算和流式读取,优点是节省内存。
说明 Python 中 enumerate() 的用法
enumerate() 可以在遍历序列时同时拿到索引和值。
for index, value in enumerate(["a", "b", "c"], start=1):
print(index, value)
它比手动维护下标更简洁。
解释 Python 中 //、% 和 ** 运算符
//:- 整除,返回向下取整后的商。
%:- 取模,返回余数。
**:- 幂运算。
7 // 2 # 3
7 % 2 # 1
2 ** 3 # 8
Python 有哪些特点和优点?
常见特点和优点:
- 语法简洁,学习成本低
- 开发效率高
- 标准库和第三方生态丰富
- 跨平台
- 支持面向对象、函数式、脚本式等多种编程风格
- 适合 Web、自动化、数据分析、AI 等多个领域
Python 中深拷贝和浅拷贝有什么区别?
浅拷贝只拷贝最外层对象,内部嵌套对象仍然共享引用。
深拷贝会递归复制所有层级对象,新旧对象互不影响。
常用 copy.copy() 做浅拷贝,copy.deepcopy() 做深拷贝。
Python 中的列表和元组有什么区别?
- 列表
list可变,元组tuple不可变。 - 列表适合频繁增删改,元组适合表示不希望被修改的数据。
- 元组通常比列表更轻量,能作为字典键的前提之一是其内部元素也必须可哈希。
什么是 Python 中的三元表达式?
Python 的三元表达式用于简化简单条件判断。
result = "成年" if age >= 18 else "未成年"
格式是:值1 if 条件 else 值2。
请简单介绍 Python 的 Flask 框架,有什么作用?
Flask 是一个轻量级 Python Web 框架,核心简单、扩展灵活。 它常用于开发 Web 网站、RESTful API、后台管理系统和小型服务。 相比 Django,Flask 更轻、更自由,但很多功能需要自己选扩展来组合。
如何在 Python 中管理内存?
Python 主要通过引用计数管理对象生命周期,并辅以垃圾回收机制处理循环引用。 开发中通常不需要手动释放内存,但要注意:
- 及时关闭文件和网络连接
- 避免不必要的大对象长期持有
- 合理使用生成器
- 避免循环引用和缓存失控
Python 中 help() 函数和 dir() 函数有什么作用?
help():- 查看对象、函数、类、模块的帮助文档。
dir():- 查看对象可用的属性和方法列表。
它们都很适合调试和学习新模块时使用。
Python 程序退出时,是否释放所有内存分配?
通常来说,进程退出后,操作系统会回收该进程占用的内存资源。 但如果程序退出前有未刷盘的数据、未关闭的文件或外部资源句柄,可能会带来业务层面的资源问题,所以仍建议显式释放关键资源。
什么是 Python 的字典,有哪些用法?
字典 dict 是键值对映射结构,特点是查找快、读取方便。
常见用法包括:
- 存储结构化数据
- 做配置映射
- 计数统计
- 实现简单的分支分发
user = {"name": "Tom", "age": 20}
print(user["name"])
什么是 Python 的负索引?
负索引表示从序列末尾开始取值。
-1 表示最后一个元素,-2 表示倒数第二个元素。
s = "python"
s[-1] # 'n'
Python 中 join() 和 split() 函数有什么区别?
join():- 把字符串序列按指定分隔符拼接成一个字符串。
split():- 把一个字符串按指定分隔符拆分成列表。
"-".join(["a", "b"]) # 'a-b'
"a-b".split("-") # ['a', 'b']
Python 是否区分大小写?
区分。
比如 name 和 Name 是两个不同的标识符。
说明 Python 中标识符的命名规则
命名规则主要有:
- 只能由字母、数字、下划线组成
- 不能以数字开头
- 不能使用关键字
- 区分大小写
规范上通常建议:
- 变量和函数使用小写加下划线
- 类名使用大驼峰
- 常量使用全大写加下划线
Python 中如何删除字符串中的前置空格?
使用 lstrip()。
s = " hello"
print(s.lstrip()) # 'hello'
Python 中如何将字符串转换为小写?
使用 lower()。
"Hello".lower() # 'hello'
Python 的 pass 语句有什么作用?
pass 表示空操作,占位用。
当语法上必须写语句,但暂时不想实现逻辑时可以使用,比如空函数、空类、空分支。
什么是 Python 的闭包?
闭包指内部函数引用了外部函数作用域中的变量,并且外部函数执行结束后这些变量仍然被保留。 它常用于封装状态、实现装饰器、工厂函数等。
什么是 Python 的关系运算符?
关系运算符用于比较两个值之间的大小或相等关系,包括:
==!=><>=<=
结果是布尔值。
什么是 Python 的赋值和算术运算符?
赋值运算符常见有:
=+=-=*=/=//=%=**=
算术运算符常见有:
+-*///%**
什么是 Python 的逻辑运算符?
逻辑运算符包括:
andornot
用于组合多个条件表达式。
什么是 Python 的成员运算符?
成员运算符用于判断某个元素是否在序列、集合、字典等对象中:
innot in
"a" in "cat" # True
1 in [1, 2, 3] # True
什么是 Python 的身份运算符?
身份运算符用于判断两个变量是否引用同一个对象:
isis not
它比较的是对象身份,不是值。
什么是 Python 的位运算符?
位运算符是直接对二进制位进行操作的运算符,包括:
&按位与|按位或^按位异或~按位取反<<左移>>右移
常用于底层控制、权限标记、性能敏感场景。
如何在 Python 中使用多进制数字?
Python 支持多种进制字面量:
- 二进制:
0b1010
- 八进制:
0o12
- 十六进制:
0xA
也可以用 bin()、oct()、hex() 做转换。
Python 中如何获取字典的所有键?
使用 dict.keys()。
d = {"a": 1, "b": 2}
print(d.keys())
如果要转成列表,可以使用 list(d.keys())。
为什么 Python 不建议使用下划线开头的标识符?
因为下划线开头通常有约定含义:
_name:- 表示内部使用,不建议外部直接访问
__name:- 会触发名称重整,常用于类内部避免命名冲突
__name__:- 通常是系统定义的特殊方法或特殊变量
所以普通业务变量不建议随意以下划线开头,避免语义混乱。
Python 如何声明多个变量并赋值?
可以链式赋值,也可以同时解包赋值。
a = b = c = 10
x, y, z = 1, 2, 3
什么是 Python 元组的解封装?
元组解封装也叫拆包,就是把元组中的多个值一次性赋给多个变量。
t = (1, 2, 3)
a, b, c = t
什么是 Python?为什么它会这么流行?
Python 是一种高级、通用、解释型编程语言。 它流行的原因主要是语法简单、开发效率高、生态强、应用范围广,既适合入门,也适合工程落地。
请列举一些 Python 的应用场景
常见场景包括:
- Web 开发
- 自动化运维与测试
- 数据分析与可视化
- 人工智能与机器学习
- 爬虫开发
- 脚本工具开发
- 教育教学
Python 有哪些局限性?
常见局限性:
- 运行速度通常不如 C/C++
- GIL 对 CPU 密集型多线程有影响
- 移动端和前端原生场景不占优势
- 某些强约束超大型项目中,动态类型维护成本会变高
请解释 Python 代码的执行过程?
简化流程可以这样理解:
- 编写
.py源代码。 - Python 解释器先把源码编译成字节码。
- 字节码交给 Python 虚拟机执行。
如果模块被导入,通常还会生成对应的 .pyc 字节码缓存文件。
Python 有哪些内置数据结构?
常见内置数据结构有:
intfloatboolstrlisttuplesetdict
此外还有 bytes、bytearray、range 等。
Python 中单引号和双引号有什么区别?
本质上没有区别,都是表示字符串。 通常根据字符串内容来选,哪个更方便少转义就用哪个。 如果字符串里本身有单引号,就可以用双引号包裹,反之亦然。
二、常用容器与流程控制
Python 中 append、insert 和 extend 有什么区别?
append(x):- 在列表末尾追加一个元素。
insert(i, x):- 在指定位置插入一个元素。
extend(iterable):- 把另一个可迭代对象中的多个元素依次追加到列表末尾。
lst = [1, 2]
lst.append(3) # [1, 2, 3]
lst.insert(1, 99) # [1, 99, 2, 3]
lst.extend([4, 5]) # [1, 99, 2, 3, 4, 5]
Python 中 break、continue、pass 有什么作用?
break:- 立即结束当前循环。
continue:- 跳过本次循环后续代码,进入下一次循环。
pass:- 什么都不做,只是占位。
Python 中 remove、del 和 pop 有什么区别?
remove(x):- 按值删除列表中第一个匹配项。
del:- 可删除指定索引元素,也可删除整个变量。
pop([i]):- 按索引删除并返回该元素,默认删除最后一个。
Python 中如何实现 switch 语句?
Python 早期没有传统 switch,常见替代方式有:
if...elif...else- 字典映射
- Python 3.10+ 的
match...case
def run(cmd):
actions = {
"start": lambda: "启动",
"stop": lambda: "停止"
}
return actions.get(cmd, lambda: "未知命令")()
Python 的 range 函数如何运用?请举例说明
range() 用于生成整数序列,常用于循环。
range(5) # 0,1,2,3,4
range(1, 5) # 1,2,3,4
range(1, 10, 2) # 1,3,5,7,9
for i in range(3):
print(i)
如何更改 Python 列表的数据类型?
如果题目想表达“把列表元素转换成其他类型”,常见做法是用列表推导式或 map()。
lst = ["1", "2", "3"]
nums = [int(x) for x in lst]
如果是把列表整体转换为其他容器,可以使用 tuple(lst)、set(lst) 等。
Python 中怎么注释代码?
- 单行注释:
- 使用
#
- 使用
- 多行说明:
- 常用连续多行
#
- 常用连续多行
- 文档字符串:
- 使用三引号,常用于模块、类、函数说明
Python 中的 != 和 is not 运算符有什么区别?
!=:- 判断值是否不相等。
is not:- 判断是不是不同一个对象。
一个比较值,一个比较身份。
Python 是否有 main 函数?
Python 没有像 C/Java 那样固定语法要求的 main 函数。
但工程里通常会写:
if __name__ == "__main__":
main()
这是一种约定,用于区分“脚本直接运行”和“模块被导入”。
Python 的 iterables 和 iterators 有什么区别?
iterable:- 可迭代对象,可以被
for遍历,比如列表、元组、字符串。
- 可迭代对象,可以被
iterator:- 迭代器,是带有状态、可逐个返回元素的对象,支持
next()。
- 迭代器,是带有状态、可逐个返回元素的对象,支持
可迭代对象通过 iter() 可以得到迭代器。
Python 中的 Map 函数有什么作用?怎么使用?
map() 会把一个函数依次作用到可迭代对象的每个元素上,返回一个迭代器。
nums = [1, 2, 3]
result = map(lambda x: x * 2, nums)
print(list(result)) # [2, 4, 6]
Python 中的 Filter 函数有什么作用?怎么使用?
filter() 用于筛选元素,把函数返回值为真的元素保留下来。
nums = [1, 2, 3, 4]
result = filter(lambda x: x % 2 == 0, nums)
print(list(result)) # [2, 4]
Python 中 reduce 函数有什么作用?怎么使用?
reduce() 会把一个函数累计作用到序列上,实现归并计算。
它位于 functools 模块中。
from functools import reduce
nums = [1, 2, 3, 4]
result = reduce(lambda x, y: x + y, nums)
print(result) # 10
什么是 Python 的 pickling 和 unpickling?
pickling:- 把 Python 对象序列化成字节流,便于保存或传输。
unpickling:- 把字节流反序列化还原成 Python 对象。
通常使用 pickle 模块。
要注意:不要反序列化不可信来源的数据,因为有安全风险。
什么是 Python 的生成器?
生成器是按需产生数据的对象,不会一次性把所有结果放入内存。
可以通过包含 yield 的函数创建,也可以用生成器表达式创建。
适合大数据处理和流式计算。
Python 中如何使用索引反转字符串?
可以使用切片:
s = "python"
print(s[::-1]) # 'nohtyp'
什么是 Python 的 Lambda 函数,有哪些应用场景?
lambda 是匿名函数,适合写简单、一次性的函数。
常见应用场景有:
map()、filter()、sorted()的key- 简单回调
- 临时计算逻辑
square = lambda x: x * x
Python 的迭代器和生成器有什么区别?
生成器本质上是一种特殊的迭代器。 区别在于:
- 迭代器是更泛化的概念,只要实现迭代协议即可
- 生成器通常由
yield自动生成,写法更简洁
所以可以说:所有生成器都是迭代器,但不是所有迭代器都是生成器。
Python 正则表达式中 match 和 search 有什么区别?
match():- 只从字符串开头开始匹配。
search():- 扫描整个字符串,找到第一个匹配位置即可。
所以 search() 的适用范围更广。
为什么 Python 中没有函数重载?
因为 Python 函数名本质上是对象引用,同名函数后定义的会覆盖前定义的。 Python 更鼓励通过默认参数、可变参数、关键字参数、类型判断等方式实现“类似重载”的效果。
三、对象模型、函数与作用域
Python 的 init 和 new 方法有什么区别?
__new__:- 负责创建实例,返回对象本身。
__init__:- 负责初始化实例,在对象创建后执行。
__new__ 常见于不可变对象子类化、单例模式等场景,普通业务里更常用的是 __init__。
你知道哪些 Python 魔术方法?
常见魔术方法包括:
__init__:- 初始化
__new__:- 创建实例
__str__/__repr__:- 字符串表示
__len__:- 长度
__iter__/__next__:- 迭代
__getitem__/__setitem__:- 下标访问
__enter__/__exit__:- 上下文管理
__call__:- 对象可调用
Python 函数参数 *arg 和 **kwargs 有什么区别?怎么使用?
*args:- 接收位置参数,多余参数会打包成元组。
**kwargs:- 接收关键字参数,多余参数会打包成字典。
def func(*args, **kwargs):
print(args)
print(kwargs)
请介绍 Python 中变量的作用域?
Python 常见作用域可以记成 LEGB:
Local:- 局部作用域
Enclosing:- 外层嵌套函数作用域
Global:- 全局作用域
Built-in:- 内置作用域
变量查找顺序通常按这个顺序进行。
Python 2 和 Python 3 有什么区别?
常见区别包括:
print:- Python 2 是语句,Python 3 是函数
- 字符串默认编码处理不同,Python 3 区分更清晰
range:- Python 3 返回惰性对象
xrange在 Python 3 中被移除- 除法行为有变化,Python 3 中
/更符合真实除法 - Python 3 对 Unicode 支持更好
面试里一般补一句:现在新项目基本都使用 Python 3。
什么是 “猴子补丁”(monkey patching)?
猴子补丁是指在运行时动态修改模块、类或对象的属性或方法。 它很灵活,常用于测试、临时修复、mock,但滥用会让代码可维护性变差。
如何在 Python 中实现字符串替换操作?
最常用的是 replace()。
s = "hello world"
print(s.replace("world", "python"))
复杂替换可以使用正则表达式的 re.sub()。
Python 在什么情况下会出现 KeyError、TypeError、ValueError?
KeyError:- 访问字典中不存在的键。
TypeError:- 操作或函数作用在了不合适的类型上。
ValueError:- 类型没错,但值本身不合法。
int("abc") # ValueError
什么是 Python 中的模块和包?
- 模块:
- 一个
.py文件就是一个模块。
- 一个
- 包:
- 一个包含多个模块的目录,用于组织代码。
简单理解:模块是代码文件级别的复用,包是目录级别的组织。
你知道哪些 Python 的编码规范?
最常见的是遵循 PEP 8。
例如:
- 命名风格统一
- 缩进用 4 个空格
- 每行长度适中
- 导入顺序规范
- 类、函数、模块之间留空行
- 写有意义的注释和文档字符串
Python 的类和对象有什么区别?
- 类是抽象模板,定义属性和方法。
- 对象是类的具体实例,是运行时真正创建出来的实体。
可以理解成“类是图纸,对象是按图纸造出来的东西”。
什么是 Python 类中的 self?
self 表示当前实例对象本身。
实例方法的第一个参数默认写成 self,通过它访问实例属性和其他实例方法。
init 方法在 Python 中有什么作用?
__init__ 是实例初始化方法,在创建对象后自动调用。
它通常用于给实例属性赋初值、建立对象初始状态。
什么是 Python 的 OOPS(面向对象编程)?
OOPS 就是面向对象编程思想,通过类和对象组织程序。 其核心特性通常包括:
- 抽象
- 封装
- 继承
- 多态
什么是 Python 面向对象的抽象特性?
抽象就是提取事物的核心特征,隐藏不必要的实现细节。 在 Python 中可以通过类、接口风格设计、抽象基类等方式体现抽象。
什么是 Python 面向对象的封装特性?
封装就是把数据和操作数据的方法绑定在一起,并对外隐藏实现细节。 这样可以降低耦合、提高安全性和可维护性。
什么是 Python 面向对象的多态特性?
多态是指同一个接口,不同对象可以有不同实现。 在 Python 中,多态更多依赖鸭子类型,不强调必须继承同一个父类。
Python 是否支持多重继承?
支持。 一个类可以继承多个父类。 但多重继承会带来方法查找顺序和设计复杂度问题,所以实际使用要谨慎。
什么是鸭子类型(duck typing)?
鸭子类型强调“关心对象能做什么,而不是它是什么类型”。 只要对象实现了需要的方法或行为,就可以被当作该类型使用。 这是 Python 动态语言风格的重要体现。
为什么 Python 执行速度慢,如何改进?
慢的原因主要有:
- 动态类型带来额外开销
- 解释执行开销更高
- GIL 对某些并发场景有限制
优化方式包括:
- 使用更高效的数据结构和算法
- 减少 Python 层循环
- 使用生成器节省内存
- 借助
numpy、pandas、cython - CPU 密集型任务改用多进程或 C 扩展
如何分析 Python 代码的执行性能?
常见方法有:
- 用
time或timeit做简单耗时测试 - 用
cProfile做性能分析 - 用
line_profiler看热点代码 - 观察内存可用
memory_profiler - 针对 SQL、网络、I/O 进一步分层分析
四、文件、标准库与常见工具
Python 中如何读取大文件,例如内存只有 4G,如何读取一个大小为 8G 的文件
核心思路是分块或逐行读取,不要一次性加载到内存。
常见做法:
- 直接遍历文件对象逐行读取
- 使用
read(size)分块读取 - 使用生成器封装处理逻辑
with open("big.log", "r", encoding="utf-8") as f:
for line in f:
process(line)
你使用过哪些 Python 标准库模块?
常见可以回答:
os、sysjson、redatetimecollectionsfunctoolsitertoolsloggingthreading、multiprocessingunittest
面试里最好补你在项目里真实用过的几个模块和场景。
Python 的 re 模块中 split()、sub()、subn() 方法有什么作用?
re.split():- 按正则规则切分字符串
re.sub():- 按正则替换字符串
re.subn():- 和
sub()类似,但会额外返回替换次数
- 和
import re
re.split(r"\s+", "a b c")
re.sub(r"\d+", "*", "a123b")
Python 的 namedtuple 有什么作用?怎么使用?
namedtuple 是带字段名的元组,可读性比普通元组更好,同时仍保留元组轻量、不可变的特点。
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(1, 2)
print(p.x, p.y)
说明 Python 中的 zip 函数
zip() 用于把多个可迭代对象按位置打包成元组迭代器。
names = ["Tom", "Jerry"]
ages = [20, 18]
print(list(zip(names, ages)))
常用于并行遍历,也常用于矩阵转置。
如何使用 Python 的 random 模块生成随机数、实现随机乱序和随机抽样?
常见方法:
random.random():- 生成
0~1之间随机浮点数
- 生成
random.randint(a, b):- 生成指定区间随机整数
random.shuffle(lst):- 原地打乱列表
random.choice(seq):- 随机取一个元素
random.sample(seq, k):- 随机抽样多个不重复元素
五、并发编程与性能
Python 中如何实现多线程?
可以使用 threading 模块创建线程,也可以用 concurrent.futures.ThreadPoolExecutor 使用线程池。
多线程更适合 I/O 密集型任务,比如网络请求、文件读写。
请介绍 Python 中多线程和多进程的应用场景,以及优缺点?
多线程:
- 适合 I/O 密集型任务
- 线程创建和切换成本相对较低
- 共享内存方便
- 但受 GIL 影响,CPU 密集型任务提升有限
多进程:
- 适合 CPU 密集型任务
- 可以利用多核
- 进程隔离更安全
- 但创建成本更高,通信更复杂
请解释 Python 线程池的工作原理?
线程池本质上是预先创建或统一管理一组线程,把任务放进任务队列后,由空闲线程不断取任务执行。
好处是避免频繁创建和销毁线程,提高资源利用率,也便于控制并发数量。
Python 中常用 ThreadPoolExecutor 来实现线程池。
from concurrent.futures import ThreadPoolExecutor
def task(x):
return x * x
with ThreadPoolExecutor(max_workers=4) as pool:
results = list(pool.map(task, [1, 2, 3, 4]))
复习建议
如果你是为了面试准备,建议把这些题再按下面几类二次记忆:
- 基础语法:
is/==、运算符、字符串、列表、字典
- 函数与高级特性:
- 装饰器、闭包、生成器、lambda、
*args/**kwargs
- 装饰器、闭包、生成器、lambda、
- 面向对象:
- 继承、封装、多态、鸭子类型、魔术方法
- 文件与标准库:
read系列、re、random、collections
- 并发与性能:
- 多线程、多进程、线程池、性能分析
面试回答时尽量遵循这个模板:
- 先下定义。
- 再说核心区别或特点。
- 最后补一个简单例子或实际应用场景。
这样会比只背概念更像真实项目型候选人。