高频 Python 面试题解析(三)
引言
在 Python 面试中,除了基础语法和数据结构,还会涉及到面向对象编程、多线程、进程管理、内存管理等更深入的问题。本篇文章将继续分析一些高频 Python 面试题,帮助你更好地应对技术面试。
1. Python 中的可变对象与不可变对象
问题:Python 中哪些是可变对象,哪些是不可变对象?它们的区别是什么?
-
可变对象(Mutable):内容可以修改,内存地址不变,例如
list
、dict
、set
。 -
不可变对象(Immutable):内容不能修改,修改时会创建新的对象,例如
int
、float
、str
、tuple
。
代码示例
# 不可变对象示例
a = 10
print(id(a)) # 获取变量 a 的内存地址
a += 1
print(id(a)) # a 变化后,内存地址发生改变
# 可变对象示例
lst = [1, 2, 3]
print(id(lst)) # 获取 lst 的内存地址
lst.append(4)
print(id(lst)) # 追加元素后,内存地址不变
解析
-
不可变对象修改时会创建新的对象,导致
id()
发生变化。 - 可变对象修改时不会改变内存地址,直接在原对象上修改数据。
2. Python 中的 is
和 ==
的区别
问题:is
和 ==
有什么区别?
-
is
比较的是对象的内存地址,是否是同一个对象。 -
==
比较的是对象的值,即对象的内容是否相等。
代码示例
a = [1, 2, 3]
b = a # 赋值引用
c = [1, 2, 3] # 创建新对象
print(a is b) # True,a 和 b 指向同一对象
print(a == b) # True,a 和 b 的值相等
print(a is c) # False,a 和 c 是不同对象
print(a == c) # True,a 和 c 的值相等
解析
-
is
用于判断两个变量是否是同一个对象(内存地址是否相同)。 -
==
仅判断对象的值是否相等,不关心对象是否是同一个。
3. Python 多线程与多进程
问题:Python 中的多线程和多进程的区别是什么?
- 多线程(threading) 适用于 I/O 密集型任务(如网络请求、文件读写)。
- 多进程(multiprocessing) 适用于 CPU 密集型任务(如计算密集型任务),可以利用多核 CPU 计算能力,避免 GIL 限制。
代码示例
import threading
import multiprocessing
import time
def task(name):
print(f"Task {name} is running")
time.sleep(2)
print(f"Task {name} is finished")
# 多线程
t1 = threading.Thread(target=task, args=("Thread-1",))
t2 = threading.Thread(target=task, args=("Thread-2",))
t1.start()
t2.start()
t1.join()
t2.join()
# 多进程
p1 = multiprocessing.Process(target=task, args=("Process-1",))
p2 = multiprocessing.Process(target=task, args=("Process-2",))
p1.start()
p2.start()
p1.join()
p2.join()
解析
- 多线程 由于 GIL 限制,无法真正实现 CPU 并行,但适用于 I/O 任务(如爬虫)。
- 多进程 通过创建独立的进程,真正实现并行计算,适合计算密集型任务。
4. Python 的垃圾回收机制
问题:Python 是如何进行垃圾回收的?
Python 使用 引用计数 作为主要的垃圾回收机制,同时结合 标记-清除(Mark and Sweep) 和 分代回收(Generational GC) 来优化内存管理。
代码示例(引用计数)
import sys
a = [1, 2, 3]
b = a # b 指向 a
print(sys.getrefcount(a)) # 获取 a 的引用计数(通常比实际多 1)
del b # 删除 b
print(sys.getrefcount(a)) # 引用计数减少
解析
- 引用计数:对象的引用数归零时,Python 自动释放内存。
- 标记-清除:处理循环引用的问题。
- 分代回收:将对象分代,提高垃圾回收的效率。
5. Python 交换两个变量的值
问题:Python 如何交换两个变量的值?
Python 提供了不使用临时变量的方式来交换两个变量的值。
代码示例
a, b = 5, 10
a, b = b, a # 交换
print(a, b) # 输出: 10 5
解析
- Python 通过元组解包 (
tuple unpacking
) 轻松交换变量值,无需使用临时变量。
6. Python 中的 *args
和 **kwargs
问题:*args
和 **kwargs
有什么区别?
-
*args
用于传递可变数量的位置参数。 -
**kwargs
用于传递可变数量的关键字参数。
代码示例
def example_function(*args, **kwargs):
print("位置参数:", args)
print("关键字参数:", kwargs)
example_function(1, 2, 3, name="Alice", age=25)
输出
位置参数: (1, 2, 3)
关键字参数: {'name': 'Alice', 'age': 25}
解析
-
*args
将多个位置参数打包为元组。 -
**kwargs
将多个关键字参数打包为字典。
结语
本文介绍了 Python 面试中的一些高频问题,包括可变对象与不可变对象、is
和 ==
的区别、多线程与多进程、垃圾回收机制、变量交换以及 *args
和 **kwargs
的使用。希望这些知识能帮助你在面试中更加自信地回答相关问题。