Skip to content

华为OD杭州 Python技术一面 - 八股文备考指南

字数
4308 字
阅读时间
20 分钟

基于 python.txt 整理 + 高频面试题补充


第一部分:核心基础题(txt原文)

1. Python基础数据类型

类型分类可变/不可变说明
int, float, complex数值类型不可变赋值即创建新对象
str字符串不可变拼接/替换生成新字符串
tuple元组不可变创建后不能增删改
list列表可变可以增删改查
dict字典可变key必须是不可变类型
set, frozenset集合set可变, frozenset不可变去重+集合运算
bytes, bytearray字节bytes不可变, bytearray可变二进制数据处理
bool布尔不可变是int的子类,只有True/False
None空值不可变单例对象

记忆技巧:基本数据类型(数值、字符串、元组)都是不可变的;容器类型中list、dict、set是可变的。


2. 字典、列表、元组的区别

特性list (列表)tuple (元组)dict (字典)
表示符号[](){}
可变性可变不可变可变
存储方式有序元素集合有序不可变集合键值对集合
访问方式索引/切片索引/切片key访问
查找效率O(n) 遍历O(n) 遍历O(1) 哈希
使用场景存同类可变元素存固定结构数据存键值映射关系

元组的特殊用途

  • 作为函数返回多值的载体
  • 作为字典的key(list不行)
  • 记录固定结构的数据(如数据库记录)

3. 常用内置函数

字符串常用方法(至少6个)

python
s = "  Hello, World  "

# 1. len() - 长度
len(s)  # 返回15

# 2. upper() / lower() - 大小写转换
s.upper()   # "  HELLO, WORLD  "
s.lower()   # "  hello, world  "

# 3. strip() - 去首尾空白
s.strip()   # "Hello, World"
s.rstrip()  # 去右侧
s.lstrip()  # 去左侧

# 4. find() / rfind() - 查找子串
s.find("World")   # 返回索引,找不到返回-1
s.rfind("o")      # 从右侧找

# 5. index() / rindex() - 同find但找不到报错
s.index("World")  # 返回索引
# s.index("xyz")  # ValueError

# 6. replace() - 替换
s.replace("World", "Python")  # "  Hello, Python  "

# 7. split() / join() - 分割/拼接
s.split(",")              # ["  Hello", " World  "]
"-".join(["a","b","c"])   # "a-b-c"

# 8. startswith() / endswith() - 前缀/后缀判断
s.startswith("  Hello")  # True
s.endswith("World  ")    # True

# 9. count() - 计数
s.count("l")  # 3

# 10. format() / f-string - 格式化
"{} age {}".format("Tom", 20)  # "Tom age 20"
name, age = "Tom", 20
f"{name} age {age}"            # "Tom age 20"

list常用方法(增删改查)

python
lst = [1, 2, 3]

# 增
lst.append(4)       # 末尾追加 → [1,2,3,4]
lst.insert(0, 0)    # 指定位置插入 → [0,1,2,3,4]
lst.extend([5,6])   # 扩展 → [0,1,2,3,4,5,6]

# 删
lst.remove(0)       # 按值删除第一个匹配项 → [1,2,3,4,5,6]
lst.pop()           # 弹出末尾元素,可指定索引
del lst[0]          # 按索引删除

# 改
lst[0] = 100        # 直接索引赋值

# 查
lst.index(3)        # 查找值的索引
lst.count(3)        # 统计出现次数
3 in lst            # 成员判断

# 排序
lst.sort()          # 原地排序
sorted(lst)         # 返回新排序列表
lst.reverse()       # 反转

4. 面向对象三大特性

特性概念示例
封装将数据和方法包装在类中,隐藏内部实现,对外提供接口class中定义私有属性__attr
继承子类获取父类的属性和方法,实现代码复用class Dog(Animal)
多态不同类有相同的方法名但实现不同,调用时动态决定Animal.speak()Dog.speak() 行为不同

重写 vs 重载

概念定义Python支持情况
重写(Override)子类重新实现父类的方法,方法签名必须相同✅ 支持,Python原生支持
重载(Overload)同一个方法名根据参数类型/数量不同有不同实现❌ Python不原生支持,但可用默认参数/*args模拟

重写示例

python
class Animal:
    def speak(self):
        return "Animal speaks"

class Dog(Animal):
    def speak(self):  # 重写父类方法
        return "Dog barks"

模拟重载

python
def add(a, b, c=0):
    return a + b + c
add(1, 2)      # 3
add(1, 2, 3)   # 6

5. lambda函数(匿名函数)

概念

lambda是一个表达式,不是语句。函数的结果就是表达式的值。可以用在任何需要函数对象的地方。

示例

python
# 1. 计算两数平方和
f = lambda x, y: x**2 + y**2
f(3, 4)  # 25

# 2. 筛选偶数(配合filter)
nums = [1, 2, 3, 4, 5, 6]
evens = list(filter(lambda x: x % 2 == 0, nums))  # [2, 4, 6]

# 3. 转换平方(配合map)
squares = list(map(lambda x: x**2, [1, 2, 3, 4, 5]))  # [1, 4, 9, 16, 25]

# 4. 配合sorted的key参数
students = [("Alice", 90), ("Bob", 85), ("Charlie", 95)]
sorted(students, key=lambda x: x[1])  # 按分数排序

6. 深拷贝 vs 浅拷贝

核心区别

类型拷贝行为嵌套可变类型变化
赋值 b = a不拷贝,两个变量指向同一对象改a则b也变
浅拷贝 b = copy.copy(a)拷贝外层对象,内层引用共享子变父也变
深拷贝 b = copy.deepcopy(a)完全独立的新对象(递归拷贝)子变父不变

示例

python
import copy

a = [[1, 2], [3, 4]]

# 赋值
b = a
a[0].append(99)
# b也变成[[1,2,99],[3,4]]

# 浅拷贝
c = copy.copy(a)
a[0].append(88)
# c的[0]也变成[1,2,99,88](内层引用共享)
# 但c.append([5,6]) 不影响a(外层是新对象)

# 深拷贝
d = copy.deepcopy(a)
a[0].append(77)
# d完全不受影响

7. 装饰器

概念

装饰器是一种在不修改原函数代码的情况下,给函数增加额外功能的机制。本质上是闭包的应用。

为什么用装饰器?

  • 代码复用:多个函数需要相同的日志、权限、计时等功能
  • 无侵入性:不需要修改原函数的业务逻辑
  • 关注点分离:把横切关注点(logging、caching等)从业务逻辑中分离

手写装饰器示例

python
def timer(func):
    import time
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        print(f"耗时: {time.time() - start}s")
        return result
    return wrapper

@timer  # 使用装饰器语法糖
def slow_func():
    time.sleep(1)
    return "done"

slow_func()  # 自动打印耗时

常见装饰器

装饰器作用
@classmethod类方法,第一个参数是cls
@staticmethod静态方法,不需要self/cls
@property将方法变为属性访问
@pytest.fixture测试夹具,提供预定义数据
@pytest.mark.parametrize参数化测试用例
@langchain_core.tools.toolLangChain工具装饰器(你的项目中用到了!)
FastAPI的@app.get/@app.post路由装饰器

8. 列表推导式

基本语法

[表达式 for 变量 in 可迭代对象 if 条件]

示例

python
# 1. 1-10的平方
squares = [i**2 for i in range(1, 11)]
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

# 2. 1-10的偶数平方
even_squares = [i**2 for i in range(1, 11) if i % 2 == 0]
# [4, 16, 36, 64, 100]

# 3. 字符串处理
names = ["Alice", "Bob", "Charlie"]
upper_names = [name.upper() for name in names]

# 4. 二维列表展平
matrix = [[1, 2, 3], [4, 5, 6]]
flat = [x for row in matrix for x in row]  # [1,2,3,4,5,6]

# 5. 条件嵌套(用else)
labels = ["even" if i % 2 == 0 else "odd" for i in range(1, 6)]
# ['odd', 'even', 'odd', 'even', 'odd']

9. 字典推导式

基本语法

{key: value for 变量1, 变量2 in 可迭代对象 if 条件}

示例

python
# 1. 从两个列表生成字典(用zip配对)
keys = ["name", "age", "city"]
values = ["Tom", 20, "Hangzhou"]
d = {k: v for k, v in zip(keys, values)}
# {"name": "Tom", "age": 20, "city": "Hangzhou"}

# 2. 给字典值+1
dd = {"a": 1, "b": 2, "c": 3}
dd_new = {k: v + 1 for k, v in dd.items()}
# {"a": 2, "b": 3, "c": 4}

# 3. 统计字符串中每个字符出现次数
text = "hello world"
char_count = {c: text.count(c) for c in set(text)}

# 4. 过滤掉值为空的字典
data = {"name": "Tom", "email": None, "phone": "123"}
clean = {k: v for k, v in data.items() if v is not None}
# {"name": "Tom", "phone": "123"}

10. 三元运算符

基本语法

值1 if 条件 else 值2

示例

python
# 1. 两数取较大值
a, b = 10, 20
max_val = a if a > b else b  # 20

# 2. 成绩评定(嵌套三元)
score = 85
grade = "优秀" if score >= 90 else (
    "良好" if score >= 80 else (
        "及格" if score >= 60 else "不及格"
    )
)
# "良好"

# 3. 列表过滤
nums = [1, 2, 3, 4, 5]
result = ["big" if n > 3 else "small" for n in nums]
# ['small', 'small', 'small', 'big', 'big']

11. Python常用库

标准库

用途示例
os / sys操作系统/系统参数os.path.join(), sys.argv
jsonJSON序列化/反序列化json.dumps(), json.loads()
re正则表达式re.match(), re.findall()
datetime日期时间处理datetime.now(), timedelta
collections高级数据结构Counter, defaultdict, OrderedDict
itertools迭代器工具chain(), product(), combinations()
copy深浅拷贝copy(), deepcopy()
logging日志记录basicConfig(), getLogger()
threading / multiprocessing多线程/多进程Thread, Process
asyncio异步IOasyncio.run(), await

常用第三方库

用途
pandas数据分析、处理Excel/CSV
numpy数值计算、数组运算
requestsHTTP请求
beautifulsoup4 / lxmlHTML/XML解析
selenium浏览器自动化
fastapi现代Web框架
flask轻量级Web框架
django全栈Web框架
pydantic数据校验/类型注解
sqlalchemyORM框架
langchainLLM应用开发框架

12. 正则表达式

常用方法对比

方法作用返回值搜索范围
re.match()从字符串开头匹配Match对象或None只匹配开头
re.search()扫描整个字符串找第一个匹配Match对象或None全字符串,找第一个
re.findall()所有匹配,返回列表列表全字符串,所有匹配
re.sub()替换匹配内容新字符串全字符串,默认替换所有

示例

python
import re

text = "Python3 is great. Python2 is old. python3.10"

# match - 只从开头找
re.match(r"Python", text)  # Match对象
re.match(r"Python", " " + text)  # None(不是开头)

# search - 找第一个
re.search(r"Python", text)  # Match对象(第一个Python)

# findall - 找所有
re.findall(r"[Pp]ython\d*", text)  # ["Python3", "Python2", "python3"]

# sub - 替换
re.sub(r"\d+", "N", text)  # "PythonN is great. PythonN is old. pythonN.N"

# 常用正则模式
# 邮箱: r"[\w.-]+@[\w.-]+\.\w+"
# 手机号: r"1[3-9]\d{9}"
# URL: r"https?://[\w./-]+"

13. 迭代器、可迭代对象、生成器

核心概念

概念定义特点
可迭代对象(Iterable)能被for循环遍历的对象实现了__iter__()__getitem__(),如list、dict、str
迭代器(Iterator)实现了__iter__()__next__()的对象__iter__()返回自身,__next__()返回下一个值或抛StopIteration
生成器(Generator)一种特殊的迭代器,用yield关键字惰性生成,节省内存,每次只产生一个值

关系图

Iterable → (调用__iter__) → Iterator → (调用__next__) → 逐个取值

示例

python
# 可迭代对象
my_list = [1, 2, 3]
for x in my_list: ...  # for循环自动调用__iter__获取迭代器

# 迭代器
my_iter = iter(my_list)  # 调用__iter__
next(my_iter)  # 1
next(my_iter)  # 2
next(my_iter)  # 3
# next(my_iter) → StopIteration

# 生成器
def my_gen(n):
    for i in range(n):
        yield i ** 2

g = my_gen(5)
next(g)  # 0
next(g)  # 1
# 惰性计算,省内存

# 列表推导式 vs 生成器表达式
lst = [i**2 for i in range(10000)]    # 一次性全部生成,占内存
gen = (i**2 for i in range(10000))    # 惰性生成,省内存

14. 冒泡排序

代码实现

python
def bubble_sort(arr):
    n = len(arr)
    # 外层循环:控制排序轮数
    for i in range(n - 1):
        swapped = False
        # 内层循环:两两比较并交换
        for j in range(n - 1 - i):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
                swapped = True
        # 优化:如果本轮没有发生交换,说明已经有序
        if not swapped:
            break
    return arr

# 测试
print(bubble_sort([64, 34, 25, 12, 22, 11, 90]))
# [11, 12, 22, 25, 34, 64, 90]

复杂度分析

  • 时间复杂度:O(n²)(最坏/平均),O(n)(最好,已有序时)
  • 空间复杂度:O(1)(原地排序)
  • 稳定性:稳定(相等元素相对位置不变)

第二部分:高频补充题

15. Python的内存管理机制

引用计数

  • 每个对象维护一个引用计数
  • 增加引用:a = obj, b = obj, list.append(obj)
  • 减少引用:del a, 函数返回,容器删除
  • 优点:实时回收,无需等待
  • 缺点:无法处理循环引用(两个对象互相引用)

标记-清除(Mark-Sweep)

  • 从根对象出发,遍历所有引用
  • 不可达的对象标记为垃圾
  • 清理被标记的对象,释放内存
  • 解决了循环引用问题

分代回收

  • 分为三代:0代(新创建)、1代(经历过回收)、2代(长期存活)
  • 回收频率:0代最频繁,1代较少,2代最少
  • 依据:绝大多数对象都是朝生夕灭的

16. Python的GIL(全局解释器锁)

概念

GIL是一把互斥锁,确保同一时刻只有一个线程在执行Python字节码

影响

  • 多线程在CPU密集型任务中无法利用多核
  • 多线程在IO密集型任务中有用(因为IO操作时会释放GIL)

解决方案

  • 多进程multiprocessing,每个进程有独立的GIL
  • 协程asyncio,单线程实现高并发
  • C扩展:在GIL外执行计算密集型操作

总结

方案CPU密集IO密集
多线程❌ 受GIL限制✅ 有效
多进程✅ 利用多核✅ 有效
协程❌ 单线程✅ 最高效

17. 深拷贝和浅拷贝的注意点

不可变对象的拷贝

  • 对于int、str、tuple等不可变对象,浅拷贝和赋值效果类似
  • 因为不可变对象本身就不能修改
python
a = 10
b = a  # 赋值
c = copy.copy(a)  # 浅拷贝
d = copy.deepcopy(a)  # 深拷贝
# 三者指向同一个int对象,因为int不可变

自定义对象的拷贝

python
class Node:
    def __init__(self, val):
        self.val = val
        self.children = []

node1 = Node(1)
node1.children.append(Node(2))

# 浅拷贝
node2 = copy.copy(node1)
node2.val = 100  # 只影响node2
node2.children.append(Node(3))  # node1的children也会变!

# 深拷贝
node3 = copy.deepcopy(node1)
node3.children.append(Node(4))  # node1完全不受影响

18. 闭包

概念

闭包是引用了外部函数变量的内部函数。即使外部函数已经返回,内部函数仍然可以访问外部变量。

示例

python
def make_counter():
    count = 0
    def counter():
        nonlocal count  # 声明使用外部变量
        count += 1
        return count
    return counter

c = make_counter()
c()  # 1
c()  # 2
c()  # 3

用途

  • 实现装饰器
  • 实现工厂函数
  • 模拟私有变量

19. 异常处理

基本结构

python
try:
    # 可能出错的代码
    result = risky_operation()
except ValueError as e:
    # 捕获特定异常
    print(f"值错误: {e}")
except (TypeError, KeyError) as e:
    # 捕获多种异常
    print(f"类型/键错误: {e}")
except Exception as e:
    # 捕获所有异常(兜底)
    print(f"未知错误: {e}")
else:
    # 没有异常时执行
    print("操作成功")
finally:
    # 无论如何都会执行(常用于资源清理)
    cleanup()

自定义异常

python
class ValidationError(Exception):
    def __init__(self, message, field):
        self.message = message
        self.field = field
        super().__init__(message)

raise ValidationError("姓名不能为空", "name")

20. with语句和上下文管理器

概念

with语句保证资源的正确获取和释放。

示例

python
# 文件操作
with open("data.txt", "r") as f:
    content = f.read()
# 自动关闭文件

# 数据库连接
with db_connection as conn:
    conn.execute(query)
# 自动提交/回滚

# 自定义上下文管理器
class DatabaseConnection:
    def __enter__(self):
        self.conn = create_connection()
        return self.conn
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.conn.close()
        if exc_type:
            print(f"发生异常: {exc_val}")
        return False

附录:面试高频场景题速答

Q: list和tuple的区别?实际使用场景?

tuple不可变,安全且可哈希(可作为dict的key)。适合存固定结构数据,如坐标(x,y)、配置项。list适合存可变集合。

Q: 装饰器的实现原理?

闭包 + 函数作为参数。装饰器本质是一个接受函数为参数的函数,返回一个新函数。@decorator是语法糖,等价于func = decorator(func)

Q: 生成器的优势?

惰性求值,节省内存。适合处理大数据集(逐行读取、无限序列)。用yield关键字实现。

Q: 深拷贝一定要用吗?

不一定。只有当需要完全独立的副本时才用。如果只是需要一个新的引用容器,但内部元素共享,浅拷贝即可。

Q: lambda和def的区别?

lambda只能包含一个表达式,def可以包含多个语句。lambda适合写简单的一次性函数,def适合写复杂的可复用函数。

贡献者

The avatar of contributor named as freeway348 freeway348

文件历史

撰写