1.4 python 基础面试题

这些问题确实是 Python 面试中的"基础照妖镜",看似简单,但非常考验你对 Python 底层机制的掌握程度。下面我不仅给出答案,还会附上面试官想听的"加分回答"代码佐证,让你在面试中能碾压式输出。


1. *args**kwargs(可变参数)

  • 是什么
    • *args 用来接收任意数量的位置参数,打包成一个元组(tuple)。
    • **kwargs 用来接收任意数量的关键字参数,打包成一个字典(dict)。
  • 核心用途 :实现函数参数的动态传递,或者装饰器中无缝传递原函数参数。
  • 加分回答(面试官眼前一亮) : "除了收集参数,*** 还用在解包 上(func(*list))。另外,在函数定义中,* 还可以强制规定后面的参数必须用关键字传参,比如 def func(a, *, b):,这样 b 就不能通过位置传参,只能 func(1, b=2),这在设计强制可读性的 API 时非常有用。"

代码演示

python 复制代码
def test(a, b, *args, **kwargs):
    print(a, b)        # 1 2
    print(args)        # (3, 4, 5)
    print(kwargs)      # {'name': 'Tom', 'age': 18}

test(1, 2, 3, 4, 5, name='Tom', age=18)

2. rangexrange(Python 2 vs 3 的老生常谈)

  • 区别(面试必问版本差异)
    • Python 2range 直接生成一个列表(List) ,占用内存;xrange 生成一个生成器(Generator),不占内存,按需生成。
    • Python 3xrange 已被移除,range 现在等价于 Python 2 的 xrange(惰性求值)。在 Python 3 中,range 返回的是一个不可变的序列类型,支持切片和 in 操作。
  • 加分回答 : "即使在 Python 3 中,range 也不是生成器,它是一个序列对象(Sequence) 。它支持 len()in 操作,且可以重复迭代。真正的生成器是 yield 函数或者 (i for i in range(10))。"

3. pipuv(包管理的代际差异)

  • pip:Python 官方标准包管理工具。
  • uv(Astral 出品):用 Rust 写的下一代包管理工具。极致性能。
  • 区别(面试装逼利器)
    • 速度uvpip 快 10~100 倍(特别是解析依赖时)。
    • 功能集成uv 不仅替换 pip,还替换了 pip-tools(锁依赖)、virtualenv(虚拟环境管理)。
    • 锁文件uv 生成 uv.lock 保证跨环境一致性,类似 poetrypdm
  • 加分回答 : "在企业级项目中,依赖管理的痛点在于依赖冲突环境一致性pip 配合 requirements.txt 容易在多人协作时出现'在我机器上能跑'的问题。uv 通过 uv.lock 锁死所有子依赖的哈希值,结合 uv venv 创建虚拟环境,能让开发、测试、生产环境的包版本完全一致。这是目前 Python 工程化的大趋势。"

常用命令对比

bash 复制代码
pip install requests          # 旧
uv pip install requests       # 新(注意前缀)

# 创建虚拟环境
python -m venv .venv          # 旧
uv venv                       # 新,极快

4. 多线程(GIL 与适用场景)

  • 核心痛点 :Python 有 GIL(全局解释器锁),它导致同一时刻只能有一个线程执行 Python 字节码。
  • 结论
    • CPU 密集型任务 (如大量计算)→ 多线程无效 ,甚至会因为线程切换变慢。此时应用多进程(multiprocessing
    • I/O 密集型任务 (网络请求、文件读写、数据库查询)→ 多线程有效,因为线程在等待 I/O 时会释放 GIL。
  • 加分回答(拉开差距的关键) : "在 Python 3.13 中,GIL 已经支持**禁用(--disable-gil)**编译选项,PEP 703 正在推进。所以'Python 多线程不能用'这句话是不准确的。在实际工程中,如果做异步 I/O,我可能更倾向于用 asyncio(协程),它更轻量、切换开销更小,并发能力是线程的数倍。"

代码演示

python 复制代码
import threading
import time

def io_task():
    time.sleep(1)  # 模拟网络请求
    print("Done")

# 多线程在这种情况下效率极高
threads = [threading.Thread(target=io_task) for _ in range(10)]
for t in threads: t.start()
for t in threads: t.join()

5. is==(引用 vs 值)

  • == :比较是否相等。
  • is :比较内存地址是否相同(即是否指向同一个对象)。
  • 面试高频陷阱
    • a = [1,2,3]; b = [1,2,3]a == bTruea is bFalse
    • a = 256; b = 256a is bTrue(因为 Python 内部缓存了小整数 -5 到 256)。
    • a = 257; b = 257a is bFalse(超出缓存范围)。
    • 字符串驻留 :只含字母数字的短字符串,is 可能为 True;包含特殊字符或动态生成的,可能为 False
  • 加分回答 : "is 通常用于 None 判断(if x is None),这是 Python 官方推荐的写法,比 == None 更快且语义更精确,因为 None 在 Python 中是单例对象。"

💡 面试冲刺总结(怎么回答能拿高分?)

不要孤立地背定义,要把它们串起来:

"*args**kwargs 是 Python 灵活性的体现;range 的演变体现了 Python 3 对内存效率的优化;pipuv 的演进反映了 Python 工程化与性能的不断追求;多线程 必须结合 GIL 分析场景;而 is== 则是 Python 对象模型底层的直观映射。这些基础决定了我们在写大型项目时,能否写出既高效又健壮的代码。"