当前位置:首页>python>Python面试常考这100题,第27题90%的人会答错……

Python面试常考这100题,第27题90%的人会答错……

  • 2026-06-27 19:03:46
Python面试常考这100题,第27题90%的人会答错……

一、Python 基础语法与对象模型


题目 1:Python 是解释型语言吗?

考点

  • 编译型语言 vs 解释型语言的区别
  • Python 的执行机制(CPython 实现)
  • 字节码与虚拟机

解析思路

  • 从两个层面理解:源代码层面和执行层面
  • Python 源代码先编译成 .pyc 字节码,再由虚拟机解释执行
  • 严格来说是"编译+解释"混合型,但更接近解释型语言
  • 可以提到 Java/Kotlin 也是类似的机制

答案

  • 不完全是。准确地说,Python 是"先编译后解释"的语言。
  • Python 源代码(.py)首先被编译成字节码.pyc 文件),字节码是一种平台无关的低级表示。
  • 然后,字节码由 Python 虚拟机(PVM) 逐行解释执行。
  • 这种机制与 Java/Kotlin 类似(Java 编译成 .class,JVM 解释执行)。
  • 所以更准确的说法是:Python 是基于虚拟机的字节码解释型语言。

题目 2:Python 中"一切皆对象"是什么意思?

考点

  • Python 对象模型
  • 类型与类的统一
  • 一切皆对象的含义

解析思路

  • Python 中每个变量、函数、类、模块都是对象
  • 一切对象的基类是 object
  • 类型本身也是对象(如 intstrlist 都是 type 的实例)
  • 可以举例:函数可以赋值给变量,可以作为参数传递

答案

  • Python 中所有数据都是对象,包括:
    • 基本类型intstrfloatbool 等
    • 函数def 定义的函数是 function 对象
    • class 定义的类是 type 对象
    • 模块.py 文件是 module 对象
  • 例如:
print(isinstance(10, object))  # Trueprint(isinstance("hello", object))  # Trueprint(isinstance(print, object))  # True
  • 甚至 typeobject 本身也是对象,形成递归定义。
  • 这种设计使得 Python 具有极高的一致性和灵活性,函数可以赋值给变量,类可以动态创建。

题目 3:is 和 == 有什么区别?

考点

  • 对象的身份比较 vs 值比较
  • Python 对象模型(id、类型、值)
  • 小整数缓存池

解析思路

  • == 比较的是两个对象的是否相等
  • is 比较的是两个对象的身份标识(内存地址),相当于 id(a) == id(b)
  • 举例说明小整数缓存、None 等特殊情况

答案

  • == 用于判断两个对象的内容是否相等;is 用于判断两个变量是否指向同一个对象
a = [12]b = [12]print(a == b)  # True,值相等print(a is b)  # False,内存地址不同
  • 对于 None 判断,推荐使用 is None 或 is not None,因为 None 是单例对象。
  • 注意:小整数(-5~256)在 CPython 中会被缓存,所以 a = 100; b = 100; a is b 可能为 True,但这属于实现细节,不应依赖。

题目 4:Python 中可变对象和不可变对象有什么区别?

考点

  • 可变对象 vs 不可变对象的定义
  • 常见可变/不可变类型
  • 可变对象作为默认参数的坑

解析思路

  • 可变对象:值可以修改,对象地址不变(如 list、dict、set)
  • 不可变对象:值不能修改,修改会创建新对象(如 int、str、tuple)
  • 重点讲解作为函数默认参数的陷阱

答案

  • 可变对象:值可以原地修改,不会创建新对象。
    • listdictset、用户自定义类(默认)
  • 不可变对象:值不能修改,修改会创建新对象。
    • intfloatstrtuplefrozenset
# 不可变对象a = "hello"a += " world"# 创建了新字符串,原来的被回收print(id(a))  # id 改变了# 可变对象lst = [123]lst.append(4)  # 原地修改print(id(lst))  # id 不变
  • 常见陷阱:默认参数使用可变对象会导致状态累积。
defadd_item(item, items=[]):# 危险!    items.append(item)return itemsprint(add_item(1))  # [1]print(add_item(2))  # [1, 2],而非 [2]

题目 5:为什么列表不能作为字典 key?

考点

  • 字典 key 的要求(可哈希)
  • 哈希表的原理
  • 可变对象不能哈希

解析思路

  • 字典底层是哈希表,要求 key 必须可哈希
  • 可哈希 = 对象在整个生命周期中 hash 值不变 + 对象可比较
  • 列表是可变对象,修改后 hash 值会变

答案

  • 字典的 key 必须是可哈希(hashable)的对象。
  • 可哈希的条件:
    1. 对象有 __hash__() 方法,返回整数哈希值
    2. 对象有 __eq__() 方法,用于比较相等性
    3. 在整个生命周期中,哈希值必须保持不变
  • 列表是可变对象,可以原地修改,修改后哈希值会改变,破坏哈希表的一致性。
  • 元组是不可变的(除非包含可变对象),所以可以作字典 key
d = {(12): "ok"}  # 合法d = {[12]: "error"}  # TypeError

题目 6:None 应该如何判断?

考点

  • None 的特性(单例对象)
  • 判断 None 的正确方式
  • 风格约定

解析思路

  • None 是 Python 中的空值单例,只有一个实例
  • 判断 None 必须使用 is None 或 is not None
  • 不能用 == None,虽然技术上可行但不符合 PEP 8

答案

  • 使用 is None 或 is not None 判断。
result = None# 推荐写法if result isNone:    print("没有结果")# 不推荐(虽然功能相同)if result == None:    print("没有结果")
  • None 是单例对象,is 比较的是身份(内存地址),比 == 更精确、更快。
  • PEP 8 风格指南明确要求使用 is None / is not None

题目 7:Python 的布尔值判断规则是什么?

考点

  • 假值(falsy)和真值(truthy)
  • 哪些对象在布尔上下文中为 False
  • 隐式布尔转换

解析思路

  • Python 中万物皆对象,都有布尔值
  • 假值:None、False、0、0.0、''、""、()、[]、{}、set()
  • 真值:除假值以外的一切对象
  • 可以提到 bool() 函数

答案

  • Python 中所有对象都可以作为布尔值判断。
  • 假值(falsy)
    • None
    • False
    • 数值 00.00j
    • 空字符串 ''""
    • 空容器:[](){}set()
    • 实现 __bool__() 返回 False 或 __len__() 返回 0 的对象
  • 真值(truthy):除上述以外的所有对象。
bool([])  # Falsebool([0])  # True(列表有元素)bool("")  # Falsebool("False")  # True(非空字符串)
  • 面试时注意:空列表/字典/元组是假值,但不是None

题目 8:and 和 or 返回的一定是布尔值吗?

考点

  • Python 逻辑运算符的短路求值
  • and/or 返回的是操作数本身,而非布尔值
  • 短路求值机制

解析思路

  • and 和 or 返回的是实际的值,不是布尔值
  • and 找第一个假值,or 找第一个真值
  • 可以配合 bool() 函数理解

答案

  • 不一定and 和 or 返回的是操作数的,而非 True/False
  • a and b:如果 a 为假值,返回 a;否则返回 b
  • a or b:如果 a 为真值,返回 a;否则返回 b
print(0and"hello")  # 0print(1and"hello")  # helloprint(0or"hello")   # helloprint(1or"hello")   # 1
  • 常见应用:默认值赋值
name = user_input or"Anonymous"
  • 面试点:短路求值机制,避免不必要的计算。

题目 9:Python 中变量需要声明类型吗?

考点

  • 动态类型 vs 静态类型
  • Python 是动态类型语言
  • 类型注解(Type Hints)

解析思路

  • Python 是动态类型语言,变量无需声明
  • 变量在赋值时确定类型
  • 类型可以随时改变
  • 现代 Python 支持类型注解,但不强制

答案

  • 不需要。Python 是动态类型语言,变量在首次赋值时自动确定类型。
x = 10# intx = "hello"# 现在是 strx = [123# 现在是 list
  • 现代 Python(3.5+)引入了类型注解(Type Hints)
defgreet(name: str) -> str:returnf"Hello, {name}"
  • 类型注解不会强制校验类型,主要用于:
    1. IDE 代码提示
    2. 类型检查工具(mypy)
    3. 代码文档化

题目 10:Python 的类型注解会强制校验类型吗?

考点

  • 类型注解的作用
  • 静态类型检查工具(mypy)
  • 类型注解 vs 强制类型转换

解析思路

  • 类型注解是给 IDE/检查工具看的,运行时不起作用
  • 需要配合 mypy 等工具进行静态检查
  • Python 依然是动态类型语言

答案

  • 不会。类型注解(Type Hints)只是语法提示,不会在运行时强制校验。
defadd(a: int, b: int) -> int:return a + badd("1""2")  # 运行时不会报错!
  • 作用:
    1. 代码文档:让其他开发者知道期望的类型
    2. IDE 提示:提供代码补全和类型检查
    3. 静态分析:配合 mypy 进行类型检查
  • 如果需要强制类型校验,需要手动转换或使用 Pydantic 等库。

二、字符串、列表、元组、字典、集合


题目 11:字符串如何反转?

考点

  • 字符串切片
  • reversed() 函数
  • 多种反转方法及性能

解析思路

  • 切片是最简洁的方法:s[::-1]
  • reversed() 返回迭代器,需用 ''.join() 组合
  • 可以提到不同方法的适用场景

答案

  • 方法一(推荐):切片反转
s = "hello"print(s[::-1])  # olleh
  • 方法二:reversed() + join
print(''.join(reversed(s)))
  • 方法三:循环拼接(不推荐,性能差)
result = ""for c in s:    result = c + result
  • 切片详解s[start:end:step],step=-1 表示从后往前遍历。

题目 12:字符串拼接为什么推荐 join?

考点

  • 字符串拼接性能
  • join() 的实现原理
  • 避免循环拼接字符串

解析思路

  • 循环拼接 + 会产生大量临时对象
  • join() 预先分配内存,一次性完成
  • + 拼接适合少量字符串,join() 适合列表拼接

答案

  • + 拼接每次都会创建新的字符串对象,O(n²) 复杂度。
  • join() 先计算总长度,分配内存,一次性复制,O(n) 复杂度。
# 不推荐:每次+都会创建新对象result = ""for s in strings:    result += s  # 效率低# 推荐:一次分配内存result = "".join(strings)  # 效率高
  • 进阶:" ".join()",".join() 可以指定分隔符。

题目 13:split() 和 strip() 有什么区别?

考点

  • split() 字符串分割
  • strip() 去除空白字符
  • 两者的返回值类型不同

解析思路

  • split() 将字符串拆分成列表
  • strip() 去除字符串两端的空白字符
  • 参数含义不同

答案

  • split()分割,返回字符串列表
"a,b,c".split(",")  # ['a', 'b', 'c']"hello world".split()  # ['hello', 'world'],按空白字符分割
  • strip()去除两端空白(或指定字符),返回新字符串
"  hello  ".strip()  # 'hello'"###hello###".strip('#')  # 'hello'
  • 记忆技巧:strip 是"剥皮",split 是"切开"。

题目 14:列表推导式是什么?

考点

  • 列表推导式的语法
  • 推导式 vs 普通循环
  • 简洁与可读性的平衡

解析思路

  • 列表推导式是一种简洁的创建列表的方式
  • [表达式 for item in iterable if 条件]
  • 适用于简单逻辑,复杂逻辑应保持可读性

答案

  • 列表推导式是 Python 特有的语法,用于简洁地创建列表。
# 普通方式squares = []for x in range(5):    squares.append(x ** 2)# 列表推导式squares = [x ** 2for x in range(5)]print(squares)  # [0, 1, 4, 9, 16]
  • 格式:[表达式 for item in 可迭代对象]
  • 优点:代码简洁、执行效率高
  • 注意:不要为了简洁而牺牲可读性,复杂逻辑建议用普通循环。

题目 15:列表推导式中如何加条件?

考点

  • 带 if 条件的列表推导式
  • if...else 表达式
  • 条件筛选 vs 条件表达式

解析思路

  • 条件筛选:if condition 放在 for 后面
  • 条件表达式:if result_a else result_b 放在表达式位置

答案

  • 条件筛选(if 在 for 后):只保留满足条件的元素
# 筛选偶数nums = [123456]evens = [x for x in nums if x % 2 == 0]print(evens)  # [2, 4, 6]
  • 条件表达式(if...else 在表达式位置):根据条件选择不同的值
# 奇数变 0,偶数保留result = [x if x % 2 == 0else0for x in nums]print(result)  # [0, 2, 0, 4, 0, 6]

题目 16:append() 和 extend() 有什么区别?

考点

  • 列表的追加方法
  • append() 追加单个元素
  • extend() 追加可迭代对象的每个元素

解析思路

  • append() 将整个对象作为一个元素添加
  • extend() 将可迭代对象的每个元素逐一添加
  • 容易混淆的场景:追加列表

答案

  • append():将单个对象添加到列表末尾
  • extend():将可迭代对象的每个元素逐一添加到列表末尾
lst = [123]lst.append([45])print(lst)  # [1, 2, 3, [4, 5]],列表作为整体添加lst = [123]lst.extend([45])print(lst)  # [1, 2, 3, 4, 5],元素逐一添加
  • + 运算符与 extend() 效果相同:[1,2] + [3,4] → [1,2,3,4]

题目 17:list.sort() 和 sorted() 有什么区别?

考点

  • 原地排序 vs 返回新列表
  • sort() 是列表方法,sorted() 是内置函数
  • 参数含义(key、reverse)

解析思路

  • sort() 原地修改列表,返回 None
  • sorted() 返回新的排序列表,原列表不变
  • 适用场景不同

答案

  • list.sort()原地排序,直接修改原列表,返回 None
  • sorted(iterable)返回新列表,原对象不变
lst = [31415]lst.sort()print(lst)  # [1, 1, 3, 4, 5]print(lst.sort())  # Nonelst = [31415]new_lst = sorted(lst)print(new_lst)  # [1, 1, 3, 4, 5]print(lst)      # [3, 1, 4, 1, 5],原列表不变
  • 两者都支持 key 和 reverse 参数:
sorted(strings, key=len, reverse=True)  # 按长度降序

题目 18:元组一定不可变吗?

考点

  • 元组的不可变性
  • 可变对象在元组内的情况
  • 元组与列表的区别

解析思路

  • 元组本身不可变,但可以包含可变对象
  • 不可变指的是元组占位的固定性,不是内容的固定性
  • 区分"不可变"和"不可变引用"

答案

  • 不完全是。元组的"不可变"指的是元素引用不可变,而非元素内容不可变。
t = (1, [23], 4)t[0] = 10# TypeError,不能修改元素引用t[1].append(5)  # 合法!修改列表内容print(t)  # (1, [2, 3, 5], 4)
  • 如果元组只包含不可变对象(int、str、tuple),则是完全不可变的。
  • 列表可以放进元组,但元组不能放进列表后被替换。

题目 19:字典如何安全获取不存在的 key?

考点

  • dict.get() 方法
  • defaultdict
  • KeyError 处理

解析思路

  • get() 返回默认值(默认为 None),不抛异常
  • d[key] 直接访问会抛 KeyError
  • defaultdict 提供默认值逻辑

答案

  • 方法一:使用 get()
d = {"a"1}print(d.get("b"))      # Noneprint(d.get("b"0))    # 0,提供默认值
  • 方法二:使用 setdefault()
d = {"a"1}d.setdefault("b"0)   # 返回 0,并设置 d["b"] = 0
  • 方法三:使用 defaultdict
from collections import defaultdictd = defaultdict(int)  # 不存在的 key 返回 0print(d["b"])  # 0

题目 20:字典如何遍历 key 和 value?

考点

  • dict.keys()、dict.values()、dict.items()
  • 多种遍历方式
  • 性能考虑

解析思路

  • keys() 返回键的视图
  • values() 返回值的视图
  • items() 返回键值对的视图
  • 可以用多种方式遍历字典

答案

  • 遍历 keys
d = {"a"1"b"2}for key in d:    print(key)for key in d.keys():    print(key)
  • 遍历 values
for value in d.values():    print(value)
  • 遍历 key-value 对
for key, value in d.items():    print(f"{key}{value}")
  • dict.keys()dict.values()dict.items() 在 Python 3 中返回视图对象,支持迭代但不是列表

题目 21:字典推导式是什么?

考点

  • 字典推导式的语法
  • 推导式 vs 普通循环
  • 多种生成方式

解析思路

  • 字典推导式:{key: value for item in iterable}
  • 可以加条件筛选
  • 适用于快速构建字典

答案

  • 字典推导式是 Python 特有的简洁语法,用于快速创建字典。
# 普通方式squares = {}for x in range(5):    squares[x] = x ** 2# 字典推导式squares = {x: x ** 2for x in range(5)}print(squares)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}# 带条件:筛选evens = {x: x**2for x in range(5if x % 2 == 0}print(evens)  # {0: 0, 2: 4, 4: 16}# 键值对互换d = {"a"1"b"2}reversed_d = {v: k for k, v in d.items()}print(reversed_d)  # {1: 'a', 2: 'b'}

题目 22:集合有什么特点?

考点

  • 集合的特性(无序、不重复、可变)
  • 集合的底层实现(哈希表)
  • 集合 vs 列表

解析思路

  • 集合三大特点:无序、不重复、可变
  • 利用哈希表实现 O(1) 查找
  • 集合元素必须是可哈希的

答案

  • 无序:集合内元素没有固定顺序(Python 3.7+ 字典有序,但集合仍无序)
  • 不重复:自动去重,不允许重复元素
  • 可变:可以添加/删除元素
  • 要求元素可哈希:集合元素必须是不可变对象
s = {12333}print(s)  # {1, 2, 3},自动去重s.add(4)      # 添加元素s.remove(2)   # 删除元素(不存在会报错)s.discard(5)  # 删除元素(不存在不报错)
  • 适合场景:去重、成员测试、集合运算。

题目 23:集合常见运算有哪些?

考点

  • 集合的数学运算
  • union、intersection、difference
  • 对称差集

解析思路

  • 并集:union() 或 |
  • 交集:intersection() 或 &
  • 差集:difference() 或 -
  • 对称差集:symmetric_difference() 或 ^

答案

a = {1234}b = {3456}# 并集:合并所有元素print(a | b)           # {1, 2, 3, 4, 5, 6}print(a.union(b))# 交集:共同元素print(a & b)           # {3, 4}print(a.intersection(b))# 差集:A 有 B 没有print(a - b)           # {1, 2}print(a.difference(b))# 对称差集:互不包含的元素print(a ^ b)           # {1, 2, 5, 6}print(a.symmetric_difference(b))# 子集/超集判断print({12}.issubset({123}))  # Trueprint({123}.issuperset({12}))  # True

题目 24:如何统计列表中元素出现次数?

考点

  • collections.Counter
  • count() 方法
  • 字典手动统计

解析思路

  • list.count() 统计单个元素
  • Counter 统计所有元素
  • 适用不同场景

答案

  • 方法一:单个元素用 count()
lst = [122333]print(lst.count(2))  # 2
  • 方法二:统计所有元素用 Counter
from collections import Counterlst = [122333]counter = Counter(lst)print(counter)  # Counter({3: 3, 2: 2, 1: 1})print(counter[2])  # 2print(counter.most_common(2))  # [(3, 3), (2, 2)]

题目 25:如何取列表中出现最多的元素?

考点

  • Counter.most_common()
  • 自定义实现
  • 边界情况处理

解析思路

  • Counter.most_common(n) 返回前 n 个最常见元素
  • 考虑多个元素出现次数相同的情况
  • 可以自定义 key 进行排序

答案

from collections import Counterlst = [1223334444]# 最常见的元素counter = Counter(lst)most_common = counter.most_common(1)print(most_common[0][0])  # 4# 前 3 个最常见的print(counter.most_common(3))  # [(4, 4), (3, 3), (2, 2)]# 手写实现defmost_frequent(lst):ifnot lst:returnNone    counts = {}for item in lst:        counts[item] = counts.get(item, 0) + 1return max(counts, key=counts.get)

三、函数与参数


题目 26:Python 函数参数有哪些类型?

考点

  • 位置参数
  • 关键字参数
  • 默认参数
  • 可变参数(*args, **kwargs)

解析思路

  • 按参数形式分类讲解
  • 混合使用时的规则

答案

  • 位置参数:按顺序传递
defgreet(name, age):    print(f"{name} is {age}")greet("Alice"25)
  • 关键字参数:按名称传递
greet(age=25, name="Alice")
  • 默认参数:提供默认值
defgreet(name, greeting="Hello"):    print(f"{greeting}{name}")
  • 可变参数
    • *args:接收任意数量的位置参数,组成元组
    • **kwargs:接收任意数量的关键字参数,组成字典
deffunc(*args, **kwargs):    print(args, kwargs)func(123, a=4, b=5)  # (1, 2, 3) {'a': 4, 'b': 5}

题目 27:默认参数有什么坑?

考点

  • 默认参数的可变性问题
  • 默认参数只计算一次的原理
  • 正确写法

解析思路

  • 默认参数在函数定义时求值,不是在调用时
  • 可变默认参数会累积状态
  • 解决方案:用 None 作为默认值

答案

  • 陷阱:可变默认参数会被所有调用共享!
# 错误示例defadd_item(item, items=[]):    items.append(item)return itemsprint(add_item(1))  # [1]print(add_item(2))  # [1, 2],而非 [2]!
  • 原因:默认参数在函数定义时创建,只会初始化一次。
  • 正确写法
# 正确方式defadd_item(item, items=None):if items isNone:        items = []    items.append(item)return itemsprint(add_item(1))  # [1]print(add_item(2))  # [2]
  • 原则:永远不要使用可变对象(如 list、dict)作为默认参数。

题目 28:*args 是什么?

考点

  • 可变位置参数
  • 参数解包
  • args 是元组

解析思路

  • *args 收集所有位置参数成元组
  • 可以在函数定义中使用,也可以在调用时解包
  • 常见用法

答案

  • *args 允许函数接受任意数量的位置参数,收集成元组。
defsum_all(*args):    total = 0for num in args:        total += numreturn totalprint(sum_all(12345))  # 15# 解包:调用时将列表展开nums = [12345]print(sum_all(*nums))  # 15
  • * 可以用在函数定义的参数前(收集),也可以用在实参前(解包)。

题目 29:**kwargs 是什么?

考点

  • 可变关键字参数
  • kwargs 是字典
  • 常见用法

解析思路

  • **kwargs 收集所有关键字参数成字典
  • 可以与 *args 配合使用
  • 调用时解包

答案

  • **kwargs 允许函数接受任意数量的关键字参数,收集成字典。
defprint_info(**kwargs):for key, value in kwargs.items():        print(f"{key}{value}")print_info(name="Alice", age=25, city="Beijing")# name: Alice# age: 25# city: Beijing# 解包:调用时将字典展开info = {"name""Bob""age"30}print_info(**info)
  • 参数顺序规则:def func(*args, **kwargs) 或 def func(a, b, *args, **kwargs)

题目 30:Python 函数是对象吗?

考点

  • Python 一切皆对象
  • 函数作为对象
  • 函数可以赋值、传递、嵌套

解析思路

  • Python 中函数是一等公民
  • 可以赋值给变量
  • 可以作为参数传递
  • 可以作为返回值

答案

  • 是的,Python 中函数是对象,可以像任何其他对象一样使用。
defgreet(name):returnf"Hello, {name}"# 函数可以赋值给变量say_hello = greetprint(say_hello("Alice"))  # Hello, Alice# 函数可以作为参数defcall_twice(func, arg):return func(func(arg))# 函数可以作为返回值defmultiplier(n):returnlambda x: x * ndouble = multiplier(2)print(double(5))  # 10
  • 这使得 Python 支持高阶函数、装饰器等高级特性。

题目 31:什么是高阶函数?

考点

  • 高阶函数的定义
  • 常见高阶函数
  • 函数式编程

解析思路

  • 高阶函数:接收函数作为参数或返回函数的函数
  • Python 内置高阶函数:map、filter、sorted
  • 与普通函数的区别

答案

  • 高阶函数:至少满足以下条件之一的函数:
    1. 接收一个或多个函数作为参数
    2. 返回一个函数
# 接收函数作为参数defapply_twice(func, x):return func(func(x))result = apply_twice(lambda x: x * 25)print(result)  # 20# 返回函数defmake_power(exponent):defpower(base):return base ** exponentreturn powersquare = make_power(2)print(square(5))  # 25
  • Python 内置高阶函数:map()filter()sorted() 的 key 参数

题目 32:lambda 表达式是什么?

考点

  • lambda 匿名函数
  • 语法限制
  • 适用场景

解析思路

  • lambda 是单表达式函数
  • 限制:只能包含一个表达式,不能有语句
  • 适合简短函数

答案

  • lambda 是创建匿名函数的表达式,返回一个函数对象。
# 普通函数defadd(a, b):return a + b# lambda 表达式add = lambda a, b: a + bprint(add(12))  # 3
  • 语法lambda 参数: 表达式
  • 限制
    • 只能包含一个表达式
    • 不能包含语句(如 if...else 可以用三元表达式)
    • 不能有 return
  • 适用场景:一次性简单函数、回调函数、高阶函数的参数
numbers = [314159]numbers.sort(key=lambda x: -x)  # 降序排列

题目 33:map() 怎么用?

考点

  • map() 函数
  • 函数式编程
  • 返回迭代器

解析思路

  • map 接收函数和可迭代对象
  • 对每个元素应用函数
  • 返回迭代器(Python 3)

答案

  • map(func, iterable) 对可迭代对象的每个元素应用函数,返回迭代器。
# 平方每个元素numbers = [12345]squares = map(lambda x: x ** 2, numbers)print(list(squares))  # [1, 4, 9, 16, 25]# 字符串转整数strings = ["1""2""3"]ints = list(map(int, strings))  # [1, 2, 3]
  • 注意:Python 3 中 map 返回迭代器,需要 list() 转换或遍历。

题目 34:filter() 怎么用?

考点

  • filter() 函数
  • 函数式编程
  • 返回迭代器

解析思路

  • filter 接收函数和可迭代对象
  • 函数返回 True/False 决定保留
  • 返回过滤后的元素

答案

  • filter(func, iterable) 过滤可迭代对象,返回满足条件的元素。
# 筛选偶数numbers = [12345678910]evens = filter(lambda x: x % 2 == 0, numbers)print(list(evens))  # [2, 4, 6, 8, 10]# 筛选非空字符串strings = ["hello""""world"None"python"]non_empty = filter(None, strings)  # None 表示用元素本身布尔值判断print(list(non_empty))  # ['hello', 'world', 'python']
  • 注意:过滤函数返回 True 的元素会被保留。

题目 35:zip() 怎么用?

考点

  • zip() 函数
  • 并行遍历多个可迭代对象
  • 返回元组迭代器

解析思路

  • zip 将多个可迭代对象配对
  • 长度不一致时取最短
  • 可用于构建字典、并行遍历

答案

  • zip(*iterables) 将多个可迭代对象对应位置的元素配对成元组。
# 并行遍历names = ["Alice""Bob""Charlie"]ages = [253035]for name, age in zip(names, ages):    print(f"{name}{age}")# 构建字典keys = ["name""age""city"]values = ["Alice"25"Beijing"]d = dict(zip(keys, values))print(d)  # {'name': 'Alice', 'age': 25, 'city': 'Beijing'}# 解压zipped = zip(names, ages)unzipped = zip(*zipped)print(list(unzipped))  # [('Alice', 'Bob', 'Charlie'), (25, 30, 35)]
  • 长度不一致:取最短的,忽略多余元素
  • 注意:Python 3 返回迭代器。

四、作用域、闭包、装饰器


题目 36:Python 作用域查找规则是什么?

考点

  • LEGB 规则
  • 作用域链
  • 变量查找顺序

解析思路

  • Python 按照 LEGB 顺序查找变量
  • Local → Enclosing → Global → Built-in
  • 示例帮助理解

答案

  • Python 变量查找遵循 LEGB 规则
    1. **L (Local)**:当前函数内部
    2. **E (Enclosing)**:外层函数(闭包)
    3. **G (Global)**:模块(文件)级别
    4. **B (Built-in)**:Python 内置
x = "global"defouter():    x = "enclosing"definner():        x = "local"        print(x)  # 找到 local    inner()outer()  # 输出:local
  • 如果在当前作用域找不到变量,会向外层逐级查找。

题目 37:global 有什么作用?

考点

  • global 关键字
  • 在函数内修改全局变量
  • 作用域问题

解析思路

  • global 声明变量为全局变量
  • 不声明直接修改会创建局部变量
  • 正确使用方式

解析思路

  • global 关键字用于在函数内部声明/修改全局变量。
count = 0defincrement():global count      # 声明使用全局变量    count += 1increment()increment()print(count)  # 2
  • 注意:如果函数内有赋值语句但没有 global,Python 会创建同名的局部变量,不会影响全局变量。

题目 38:nonlocal 有什么作用?

考点

  • nonlocal 关键字
  • 闭包中的变量修改
  • 与 global 的区别

解析思路

  • nonlocal 用于在内层函数中修改外层函数的变量
  • global 用于修改模块级别的变量
  • 两者作用范围不同

答案

  • nonlocal 用于在内层函数中修改外层函数(非全局)的变量。
defouter():    x = 10definner():nonlocal x  # 声明修改外层函数的 x        x = 20    inner()    print(x)  # 20outer()
  • 对比
    • global:声明/修改模块级别的变量
    • nonlocal:声明/修改外层函数的变量(闭包内)
defcounter():    count = 0defincrement():nonlocal count        count += 1return countreturn incrementc = counter()print(c())  # 1print(c())  # 2

题目 39:什么是闭包?

考点

  • 闭包的定义
  • 闭包的三个条件
  • 闭包的应用

解析思路

  • 闭包是"记住"外层作用域的函数
  • 三个条件:嵌套函数、引用外层变量、返回内部函数
  • 闭包实现数据私有化

答案

  • 闭包:一个内层函数引用了外层函数的变量,并被返回给外部,这些变量不会被回收。
defmake_multiplier(factor):defmultiplier(number):return number * factor  # 引用外层变量return multipliertimes_3 = make_multiplier(3)times_5 = make_multiplier(5)print(times_3(10))  # 30print(times_5(10))  # 50
  • 闭包三要素
    1. 内层函数定义在外层函数内部
    2. 内层函数引用了外层函数的变量
    3. 外层函数返回内层函数
  • 应用:数据私有化、工厂函数、延迟计算

题目 40:什么是装饰器?

考点

  • 装饰器的定义
  • 装饰器的工作原理
  • 函数替换

解析思路

  • 装饰器是接收函数并返回新函数的函数
  • 本质是函数替换
  • 用 @ 语法糖简化调用

答案

  • 装饰器:在不修改原函数的前提下,给函数添加新功能。
deflog_calls(func):defwrapper(*args, **kwargs):        print(f"Calling {func.__name__}")        result = func(*args, **kwargs)        print(f"Finished {func.__name__}")return resultreturn wrapper@log_callsdefgreet(name):    print(f"Hello, {name}")greet("Alice")# 输出:# Calling greet# Hello, Alice# Finished greet
  • @log_calls 等价于 greet = log_calls(greet)
  • 装饰器在函数定义后立即生效。

题目 41:装饰器如何保留原函数信息?

考点

  • functools.wraps
  • 函数元信息丢失问题
  • 正确实现装饰器

解析思路

  • 直接返回 wrapper 函数会丢失原函数信息
  • 使用 functools.wraps 复制元信息
  • 必须使用

答案

  • 使用 functools.wraps 保留原函数的元信息。
import functoolsdeflog_calls(func):    @functools.wraps(func)  # 保留原函数信息defwrapper(*args, **kwargs):        print(f"Calling {func.__name__}")return func(*args, **kwargs)return wrapper@log_callsdefgreet(name):"""打招呼函数"""    print(f"Hello, {name}")print(greet.__name__)  # greet(而非 wrapper)print(greet.__doc__)   # 打招呼函数
  • 不保留的后果greet.__name__ 会变成 "wrapper",影响调试、文档、装饰器栈等。

题目 42:带参数的装饰器怎么写?

考点

  • 参数化装饰器
  • 三层函数嵌套
  • 常见用法

解析思路

  • 装饰器工厂:返回装饰器的函数
  • 三层:外层接收参数,中间层返回装饰器,最内层是 wrapper

答案

import functoolsdefrepeat(times):defdecorator(func):        @functools.wraps(func)defwrapper(*args, **kwargs):for _ in range(times):                result = func(*args, **kwargs)return resultreturn wrapperreturn decorator@repeat(times=3)defgreet(name):    print(f"Hello, {name}")greet("Alice")# 输出:Hello, Alice 三次
  • 调用链@repeat(times=3) → 返回 decorator → 装饰 greet
  • 常见参数化装饰器:@lru_cache(maxsize=128)@click.option()

五、异常处理


题目 43:Python 如何捕获异常?

考点

  • try...except 结构
  • 多个 except 子句
  • 异常捕获顺序

解析思路

  • 基本语法结构
  • 捕获特定异常 vs 捕获所有异常
  • 异常继承关系影响捕获顺序

答案

try:    result = 10 / 0except ZeroDivisionError:    print("不能除以零")# 多个异常try:    int("abc")except ValueError:    print("值错误")except TypeError:    print("类型错误")# 捕获所有异常try:    risky_operation()except Exception as e:    print(f"发生错误: {e}")
  • 捕获顺序:先捕获子类,后捕获父类
except ZeroDivisionError:  # 先匹配这个passexcept ArithmeticError:    # 父类放后面pass

题目 44:try...except...else...finally 执行顺序是什么?

考点

  • 异常处理的完整结构
  • 各子句执行时机
  • 常见用法

解析思路

  • else:没有异常时执行
  • finally:无论是否异常都执行
  • return vs finally 的执行顺序

答案

try:    print("try")# 可能抛出异常的代码    x = 10 / 2except ZeroDivisionError:    print("except: 捕获到异常")else:    print("else: 没有异常时执行")  # x = 10 / 2 成功执行后才执行finally:    print("finally: 无论是否异常都执行")
  • 执行顺序
    1. try 内的代码执行
    2. 如果有异常,匹配 except
    3. 如果没有异常,执行 else
    4. 无论是否有异常,finally 总是执行
# finally 与 returndeftest():try:return1finally:        print("finally")  # 仍然会执行test()  # 输出: finally, 返回 1

题目 45:如何主动抛出异常?

考点

  • raise 语句
  • 异常类型
  • 自定义异常

解析思路

  • 使用 raise 关键字
  • 可以 raise 异常类或异常实例
  • 在什么场景下抛出异常

答案

  • 使用 raise 关键字抛出异常。
# 抛出异常类raise ValueError("值不合法")# 抛出异常实例raise ValueError("值不合法")# 重新抛出当前异常try:    something()except:raise# 保持原始异常信息
  • 何时抛出
    • 检测到程序错误且无法处理时
    • 验证输入失败时
    • 业务规则不满足时
defwithdraw(amount):if amount <= 0:raise ValueError("取款金额必须为正数")

题目 46:如何自定义异常?

考点

  • 异常类继承
  • 自定义异常类
  • 常见模式

解析思路

  • 继承自 Exception
  • 可以添加额外属性
  • 命名习惯

答案

# 基本自定义异常classValidationError(Exception):pass# 带额外信息的异常classValidationError(Exception):def__init__(self, field, message):        self.field = field        self.message = message        super().__init__(f"{field}{message}")raise ValidationError("email""格式不正确")# 捕获自定义异常try:    ...except ValidationError as e:    print(f"字段 {e.field}{e.message}")
  • 命名习惯:以 Error 结尾
  • 最佳实践:保持简单,继承最合适的内置异常

题目 47:为什么不要直接 except Exception: pass?

考点

  • 异常处理的最佳实践
  • 裸 except 的危害
  • 正确的异常处理方式

解析思路

  • 裸 except 捕获所有异常,包括 KeyboardInterrupt
  • 掩盖真实错误
  • 应该捕获具体异常并适当处理

答案

  • 危害
    1. 捕获所有异常,包括 KeyboardInterruptSystemExit
    2. 掩盖真正的 bug,使调试困难
    3. 不处理异常,只是隐藏错误
# 错误做法try:    dangerous_operation()except:  # 捕获所有,包括退出信号pass# 正确做法try:    dangerous_operation()except SpecificError as e:    handle_error(e)  # 适当处理raise# 必要时重新抛出
  • 如果必须捕获所有:至少用 except Exception:,不要裸 except:
  • 原则:捕获你期望的异常,让未预期的异常向上传播。

六、文件、上下文管理器、迭代器、生成器


题目 48:为什么推荐使用 with open()?

考点

  • 上下文管理器
  • 资源自动释放
  • with 语句的好处

解析思路

  • 文件需要显式关闭
  • with 自动调用 enter 和 exit
  • 确保资源正确释放

答案

  • with 语句确保文件在使用完毕后自动关闭,即使发生异常。
# 不推荐:需要手动关闭f = open("file.txt""r")content = f.read()f.close()  # 如果中间出错,文件不会关闭# 推荐:自动关闭with open("file.txt""r"as f:    content = f.read()# with 块结束后,文件自动关闭
  • 原理:对象实现了 __enter__ 和 __exit__ 方法(上下文管理器协议)
  • 好处:防止资源泄漏、代码更简洁

题目 49:什么是上下文管理器?

考点

  • 上下文管理器协议
  • enter 和 exit
  • contextlib 模块

解析思路

  • 实现了 enter 和 exit 的对象
  • 自动获取和释放资源
  • 可以用 @contextmanager 装饰器实现

答案

  • 上下文管理器:实现 __enter__ 和 __exit__ 方法的对象,控制资源的获取和释放。
classFileManager:def__init__(self, filename, mode):        self.filename = filename        self.mode = mode        self.file = Nonedef__enter__(self):        self.file = open(self.filename, self.mode)return self.filedef__exit__(self, exc_type, exc_val, exc_tb):if self.file:            self.file.close()returnFalse# 不处理异常with FileManager("test.txt""w"as f:    f.write("Hello")
  • 装饰器方式:使用 @contextmanager
from contextlib import contextmanager@contextmanagerdeffile_manager(filename, mode):    f = open(filename, mode)yield f    f.close()

题目 50:什么是迭代器?

考点

  • 迭代器协议
  • iter 和 next
  • 迭代器特点

解析思路

  • 迭代器是实现了 iter 和 next 的对象
  • 每次调用 next 返回下一个元素
  • 迭代器是消耗性的

答案

  • 迭代器:实现了 __iter__ 和 __next__ 方法的对象。
classCounter:def__init__(self, n):        self.n = n        self.current = 0def__iter__(self):return selfdef__next__(self):if self.current >= self.n:raise StopIteration        self.current += 1return self.currentfor i in Counter(3):    print(i)  # 1, 2, 3
  • 特点
    • __iter__ 返回迭代器本身
    • __next__ 返回下一个元素
    • 迭代完成后抛出 StopIteration
    • 消耗性:只能遍历一次

题目 51:什么是可迭代对象?

考点

  • 可迭代协议
  • 迭代器 vs 可迭代对象
  • 常见可迭代对象

解析思路

  • 可迭代对象实现了 iter
  • 返回迭代器
  • 列表、元组、字典等都是可迭代对象

答案

  • 可迭代对象:实现了 __iter__ 方法(返回迭代器)的对象。
# 列表是可迭代对象lst = [123]iterator = lst.__iter__()  # 或 iter(lst)print(next(iterator))  # 1print(next(iterator))  # 2
  • 区别
    • 可迭代对象:可以用 for 遍历,不一定有 __next__
    • 迭代器:可以用 for 遍历,也有 __next__
  • 常见可迭代对象:list、tuple、dict、set、str、生成器

题目 52:什么是生成器?

考点

  • 生成器函数
  • yield 语句
  • 生成器表达式

解析思路

  • 生成器函数使用 yield 返回值
  • 调用时不执行,迭代时才执行
  • 生成器是迭代器

答案

  • 生成器:用 yield 语句返回值的函数,每次迭代生成一个值。
defcount_up_to(n):    i = 1while i <= n:yield i  # 暂停,返回值        i += 1gen = count_up_to(3)print(next(gen))  # 1print(next(gen))  # 2print(next(gen))  # 3
  • 工作原理
    1. 调用函数创建生成器对象(不执行)
    2. 每次 next() 执行到 yield 并暂停
    3. StopIteration 后结束
  • 生成器表达式gen = (x**2 for x in range(5))

题目 53:生成器有什么优点?

考点

  • 惰性计算
  • 内存效率
  • 适合大数据处理

解析思路

  • 生成器是惰性的,按需生成
  • 不需要一次性加载所有数据
  • 适合处理大数据流

答案

  • 惰性求值:按需计算,节省内存
# 普通列表:一次性加载所有数据numbers = [x**2for x in range(1000000)]  # 占用大量内存# 生成器:按需计算numbers = (x**2for x in range(1000000))  # 几乎不占内存
  • 优点
    1. 内存高效:不需要存储所有元素
    2. 惰性计算:按需计算,避免不必要的操作
    3. 表示无限序列:可以表示无法穷举的数据流
    4. 可组合:生成器链式调用
# 处理大文件with open("huge_file.txt"as f:    lines = (line.strip() for line in f)  # 不读取所有行for line in lines:        process(line)

题目 54:yield from 有什么作用?

考点

  • yield from 语法
  • 委托生成器
  • 子生成器

解析思路

  • yield from 用于委托给子生成器
  • 简化嵌套生成器
  • 自动处理 StopIteration

答案

  • yield from 将控制权委托给子生成器,自动传递值。
# 不使用 yield fromdefflatten(nested):for item in nested:for element in item:yield element# 使用 yield fromdefflatten(nested):for item in nested:yieldfrom itemnested = [[12], [34], [56]]print(list(flatten(nested)))  # [1, 2, 3, 4, 5, 6]
  • 作用
    1. 简化嵌套循环
    2. 在生成器链中传递值
    3. 自动处理子生成器的 StopIteration

题目 55:生成器表达式和列表推导式有什么区别?

考点

  • 生成器表达式 vs 列表推导式
  • 惰性求值 vs 即时求值
  • 内存占用

解析思路

  • 列表推导式用 [],生成器表达式用 ()
  • 列表即时生成,生成器惰性生成
  • 生成器只能遍历一次

答案

特性
列表推导式 []
生成器表达式 ()
求值时机
即时求值(立即计算)
惰性求值(按需计算)
内存占用
全部元素占用内存
只占一个元素的内存
类型
列表
生成器对象
遍历次数
可多次遍历
只能遍历一次
# 列表推导式squares_list = [x**2for x in range(1000)]print(type(squares_list))  # <class 'list'># 生成器表达式squares_gen = (x**2for x in range(1000))print(type(squares_gen))  # <class 'generator'>
  • 选择原则:需要遍历多次用列表,只需要遍历一次或数据量大用生成器。

七、面向对象


题目 56:类和对象有什么区别?

考点

  • 类与对象的概念
  • 类是模板,对象是实例
  • 关系与区别

解析思路

  • 类是抽象的蓝图,对象是具体的实例
  • 类定义属性和方法,对象具有具体的值
  • 一个类可以创建多个对象

答案

  • 类(Class):抽象的模板,定义了一类对象的共同属性和方法。
  • 对象(Object):类的具体实例,具有实际的内存空间和数据。
classDog:# 类def__init__(self, name):        self.name = namedefbark(self):        print(f"{self.name} says Woof!")# 创建对象dog1 = Dog("Buddy")dog2 = Dog("Max")print(type(dog1))  # <class '__main__.Dog'>print(isinstance(dog1, Dog))  # True
  • 类定义属性和方法,对象拥有具体的属性值

题目 57:__init__ 是构造函数吗?

考点

  • init vs new
  • 构造函数 vs 初始化器
  • Python 对象创建过程

解析思路

  • new 是构造函数,创建对象
  • init 是初始化器,初始化对象
  • 两者配合使用

答案

  • 不是__init__ 是初始化器__new__ 才是构造函数
  • __new__ 负责创建实例,__init__ 负责初始化实例。
classExample:def__new__(cls, *args, **kwargs):        print("__new__ called")return super().__new__(cls)  # 必须返回实例def__init__(self, value):        print("__init__ called")        self.value = valuee = Example(10)# 输出:# __new__ called# __init__ called
  • **大多数情况下只需重写 __init__**,__new__ 用于特殊场景(如单例模式、不可变对象)。

题目 58:实例属性和类属性有什么区别?

考点

  • 实例属性 vs 类属性
  • 命名空间
  • 访问优先级

解析思路

  • 实例属性:属于单个对象
  • 类属性:属于类本身,所有对象共享
  • 访问时先找实例,再找类

答案

classDog:    species = "Canis familiaris"# 类属性,所有对象共享def__init__(self, name):        self.name = name  # 实例属性,每个对象独立dog1 = Dog("Buddy")dog2 = Dog("Max")print(dog1.name)      # Buddy(实例属性)print(dog1.species)   # Canis familiaris(类属性)# 修改实例属性不影响类属性dog1.species = "Cat"# 创建了实例属性,不影响 dog2print(dog2.species)  # Canis familiaris
  • 区别
    • 实例属性:每个对象独立,通过 self.xxx 定义
    • 类属性:所有对象共享,通过类名.xxx 或 self.xxx 定义

题目 59:类方法、静态方法、实例方法有什么区别?

考点

  • 三种方法的定义和调用方式
  • 参数接收
  • 使用场景

解析思路

  • 实例方法:第一个参数是 self
  • 类方法:第一个参数是 cls,用 @classmethod
  • 静态方法:没有 self/cls,用 @staticmethod

答案

classExample:    class_attr = "类属性"definstance_method(self):# self 是实例return"实例方法", self    @classmethoddefclass_method(cls):# cls 是类return"类方法", cls    @staticmethoddefstatic_method():# 没有隐式参数return"静态方法"obj = Example()# 调用方式obj.instance_method()     # 需要实例Example.class_method()    # 可以用类或实例调用Example.static_method()   # 可以用类或实例调用
类型
装饰器
第一个参数
调用方式
实例方法
self
实例调用
类方法
@classmethod
cls
类或实例调用
静态方法
@staticmethod
类或实例调用

题目 60:什么是继承?

考点

  • 继承的概念
  • 基类和子类
  • 继承的好处

解析思路

  • 继承实现代码复用
  • 子类继承父类的属性和方法
  • 可以添加或重写

答案

  • 继承:子类继承父类的属性和方法,实现代码复用和层次化设计。
classAnimal:def__init__(self, name):        self.name = namedefspeak(self):raise NotImplementedErrorclassDog(Animal):# 继承 Animaldefspeak(self):returnf"{self.name} says Woof!"classCat(Animal):# 继承 Animaldefspeak(self):returnf"{self.name} says Meow!"dog = Dog("Buddy")print(dog.name)    # Buddy(继承自父类)print(dog.speak()) # Buddy says Woof!
  • 好处:减少代码重复、建立"is-a"关系、支持多态

题目 61:什么是方法重写?

考点

  • 方法重写(覆盖)
  • super() 调用父类方法
  • 多态

解析思路

  • 子类定义与父类同名的方法
  • 子类实现覆盖父类实现
  • 用 super() 调用父类方法

答案

  • 方法重写:子类定义与父类同名的方法,改变或扩展父类行为。
classParent:defgreet(self):return"Hello from Parent"classChild(Parent):defgreet(self):# 重写父类方法return"Hello from Child"defgreet_parent(self):# 调用父类方法return super().greet()child = Child()print(child.greet())          # Hello from Childprint(child.greet_parent())   # Hello from Parent
  • 重写规则
    • 方法名必须相同
    • 参数签名可以相同或修改
    • 子类方法权限不能比父类更严格

题目 62:super() 有什么作用?

考点

  • super() 函数
  • MRO(方法解析顺序)
  • 在 init 中的使用

解析思路

  • super() 调用父类的方法
  • 在子类初始化时先调用父类初始化
  • Python 3 的 super() 用法

答案

  • super() 返回一个代理对象,用于调用父类的方法。
classAnimal:def__init__(self, name, age):        self.name = name        self.age = ageclassDog(Animal):def__init__(self, name, age, breed):        super().__init__(name, age)  # 调用父类 __init__        self.breed = breed  # 添加新属性dog = Dog("Buddy"3"Golden Retriever")print(dog.name, dog.age, dog.breed)  # Buddy 3 Golden Retriever
  • Python 3 写法super().__init__(...)(不需要传类名和 self)
  • 多继承中的 MROsuper() 按照 MRO 顺序调用下一个类的方法

题目 63:Python 支持多继承吗?

考点

  • 多继承
  • MRO(方法解析顺序)
  • 多继承的复杂度

解析思路

  • Python 支持多继承
  • 可能有菱形继承问题
  • MRO 决定了方法调用顺序

答案

  • 支持。Python 支持多继承,即一个类可以继承多个父类。
classFlyer:deffly(self):        print("Flying")classSwimmer:defswim(self):        print("Swimming")classDuck(Flyer, Swimmer):# 多继承passduck = Duck()duck.fly()   # Flyingduck.swim()  # Swimming
  • MRO(方法解析顺序):Python 使用 C3 线性化算法确定方法调用顺序。
print(Duck.__mro__)  # 查看 MRO
  • 注意:多继承可能导致菱形继承和命名冲突,应谨慎使用。

题目 64:什么是魔术方法?

考点

  • 魔术方法(特殊方法/双下方法)
  • 双下划线命名
  • 常见魔术方法

解析思路

  • 魔术方法以双下划线开头和结尾
  • Python 内部调用或允许重写
  • 用于实现运算符、容器等行为

解析思路

  • 魔术方法(Magic Methods / Dunder Methods):以 __ 包裹的方法,由 Python 内部调用或允许开发者重写。
classPoint:def__init__(self, x, y):        self.x = x        self.y = ydef__add__(self, other):# 重写 + 运算符return Point(self.x + other.x, self.y + other.y)def__repr__(self):returnf"Point({self.x}{self.y})"p1 = Point(12)p2 = Point(34)print(p1 + p2)  # Point(4, 6)
  • 常见魔术方法
    • __init__:初始化
    • __str__ / __repr__:字符串表示
    • __add__ / __eq__ / __lt__:运算符
    • __len__ / __getitem__:容器行为

题目 65:__repr__ 和 str 有什么区别?

考点

  • 字符串表示方法
  • 不同场景的调用
  • IDE 友好 vs 用户友好

解析思路

  • repr 给开发者/调试用
  • str 给用户看
  • 优先调用规则

答案

  • __repr__开发者友好,用于调试和开发环境
  • __str__用户友好,用于最终用户显示
classPerson:def__init__(self, name):        self.name = namedef__repr__(self):returnf"Person(name='{self.name}')"# 精确、可以重建对象def__str__(self):returnf"Person: {self.name}"# 友好、可读p = Person("Alice")print(repr(p))  # Person(name='Alice')print(str(p))   # Person: Alice# print 优先用 __str__,没有则用 __repr__# 直接在解释器输入对象优先用 __repr__
  • 最佳实践:实现 __repr__ 优先(IDE、调试用),__str__ 可选。

题目 66:@property 有什么作用?

考点

  • 属性装饰器
  • Getter/Setter
  • Pythonic 的封装方式

解析思路

  • 用方法模拟属性
  • 避免直接暴露实例变量
  • 可以在访问时添加逻辑

答案

  • @property 将方法转换为属性访问,实现类似 getter 的功能。
classCircle:def__init__(self, radius):        self._radius = radius  # 私有属性(约定)    @propertydefradius(self):"""Getter"""return self._radius    @radius.setterdefradius(self, value):"""Setter,带验证"""if value < 0:raise ValueError("半径不能为负")        self._radius = value    @propertydefarea(self):"""只读属性"""return3.14 * self._radius ** 2c = Circle(5)print(c.radius)  # 5(像访问属性一样)c.radius = 10# 调用 setterprint(c.area)     # 314.0
  • 好处:在保持 API 简洁的同时,可以添加验证、计算等逻辑。

题目 67:什么是 dataclass?

考点

  • dataclass 装饰器
  • 自动生成方法
  • 简化数据类定义

解析思路

  • Python 3.7+ 的特性
  • 自动生成 init__、__repr__、__eq 等
  • 适合存储数据的类

答案

  • dataclass 是 Python 3.7+ 的装饰器,自动生成常用方法。
from dataclasses import dataclassfrom typing import Optional@dataclassclassPerson:    name: str    age: int    email: Optional[str] = Noneperson = Person("Alice"25)print(person)  # Person(name='Alice', age=25, email=None)print(person.name)  # Alice
  • 自动生成__init____repr____eq____hash__(可选)
  • 字段:使用类型注解定义字段
  • 参数
    • frozen=True:不可变对象
    • order=True:支持比较运算
    • slots=True:使用 __slots__ 优化内存

题目 68:__slots__ 有什么作用?

考点

  • slots 属性
  • 限制属性
  • 内存优化

解析思路

  • 限制类只能有特定的属性
  • 减少内存占用
  • 不能动态添加属性

答案

  • __slots__ 限制类只能拥有的属性,禁用 __dict__,节省内存。
classWithoutSlots:def__init__(self, name):        self.name = nameclassWithSlots:    __slots__ = ['name']def__init__(self, name):        self.name = name# __slots__ 类w1 = WithSlots("Alice")w1.name = "Bob"# OK# w1.age = 25           # AttributeError# 无 __slots__ 类w2 = WithoutSlots("Alice")w2.age = 25# OK,可以动态添加
  • 优点:内存占用小、属性访问快、限制随意添加属性
  • 缺点:不能动态添加属性、不能使用 __dict__slots 继承问题

八、模块、包、虚拟环境、工程化


题目 69:模块和包有什么区别?

考点

  • 模块(module)
  • 包(package)
  • init.py

解析思路

  • 模块是单个 .py 文件
  • 包是包含 init.py 的目录
  • 包可以包含子包

答案

  • 模块:单个 .py 文件,可以包含函数、类、变量
  • :包含 __init__.py 的目录,用于组织多个模块
# 模块# file: mymodule.pydefhello():return"Hello"# 使用模块import mymodulemymodule.hello()# 包# directory: mypackage/# file: mypackage/__init__.py# file: mypackage/module.pyimport mypackage.module
  • __init__.py 使目录成为包(Python 3.3+ 不必须,但仍建议保留)

题目 70:if name == "main" 有什么作用?

考点

  • 模块执行机制
  • name 变量
  • 脚本 vs 模块

解析思路

  • 直接运行脚本时 name == "main"
  • import 时不执行
  • 允许文件既可运行又可导入

答案

  • __name__ 是 Python 自动设置的变量:
    • 直接运行文件时:__name__ == "__main__"
    • 被 import 时:__name__ == "模块名"
# file: example.pydefmain():    print("Main function")if __name__ == "__main__":    main()# 只有直接运行此文件时才执行
  • 作用:区分"被作为脚本执行"还是"被作为模块导入"
  • 常见场景:测试代码、性能测试入口

题目 71:Python 如何管理第三方依赖?

考点

  • pip 包管理器
  • 虚拟环境
  • requirements.txt / pyproject.toml

解析思路

  • pip 是官方包管理器
  • 虚拟环境隔离依赖
  • 现代项目使用 pyproject.toml

答案

  • pip:Python 官方包管理器
pip install package_namepip install package==1.0.0pip install -r requirements.txt
  • 虚拟环境:隔离不同项目的依赖
python -m venv venvsource venv/bin/activate  # Linux/Macvenv\Scripts\activate     # Windowspip install package
  • 依赖管理文件
    • requirements.txt:列出依赖
    • pyproject.toml:现代标准(PEP 518),包含项目元数据和依赖

题目 72:requirements.txt 有什么用?

考点

  • 依赖管理
  • 环境复现
  • pip freeze

解析思路

  • 记录项目依赖
  • 方便环境复现
  • 版本锁定

答案

  • requirements.txt 记录项目的第三方依赖,便于复现环境。
# 生成 requirements.txtpip freeze > requirements.txt# 安装依赖pip install -r requirements.txt
  • 文件内容示例
requests>=2.28.0flask==2.2.0numpy>=1.23.0
  • 版本说明
    • ==:精确版本
    • >=:最低版本
    • ~=:兼容版本(如 ~=2.0 表示 >=2.0 且 <3.0)

题目 73:pyproject.toml 是什么?

考点

  • PEP 518
  • 现代项目配置
  • build system

解析思路

  • Python 3.11+ 推荐的配置方式
  • 包含项目元数据、依赖、构建配置
  • 替代 setup.py 和 requirements.txt

答案

  • pyproject.toml 是现代 Python 项目的标准配置文件(PEP 518)。
[project]name = "my-project"version = "1.0.0"dependencies = [    "requests>=2.28.0",    "flask>=2.0.0"][project.optional-dependencies]dev = [    "pytest>=7.0.0",    "black>=22.0.0"][build-system]requires = ["setuptools>=45", "wheel"]build-backend = "setuptools.build_meta"
  • 作用
    • 定义项目元数据(名称、版本、作者)
    • 声明依赖
    • 配置构建系统
  • 优势:标准化、易于解析、支持工具配置(black、mypy)

题目 74:Python 如何读取环境变量?

考点

  • os.environ
  • os.getenv
  • 环境变量类型

解析思路

  • os.environ 是字典
  • os.getenv 读取单个变量
  • 支持默认值

答案

import os# 方式一:os.environdb_host = os.environ["DB_HOST"]db_port = os.environ.get("DB_PORT""5432")  # 带默认值# 方式二:os.getenv(推荐)api_key = os.getenv("API_KEY")timeout = os.getenv("TIMEOUT""30")# 设置环境变量os.environ["DEBUG"] = "true"
  • 注意事项
    • 环境变量都是字符串
    • 需要类型转换
    • 敏感信息不要硬编码

题目 75:__all__ 有什么作用?

考点

  • 模块导出控制
  • from module import *
  • 显式导出

解析思路

  • all 定义 from module import * 时的导出内容
  • 控制模块的公共 API
  • 最佳实践

答案

  • __all__ 列表定义 from module import * 时导出的内容。
# file: mymodule.py__all__ = ['public_func''PublicClass']defpublic_func():passdef_private_func():passclassPublicClass:pass# 导入行为from mymodule import *  # 只导入 public_func 和 PublicClass
  • 作用
    1. 明确模块的公共 API
    2. 隐藏内部实现
    3. 避免命名冲突
  • 命名约定:以下划线 _ 开头的函数/类是私有约定

九、并发、线程、进程、协程


题目 76:线程适合什么场景?

考点

  • 线程的特点
  • I/O 密集型 vs CPU 密集型
  • GIL 的影响

解析思路

  • 线程适合 I/O 密集型任务
  • 不适合 CPU 密集型(受 GIL 限制)
  • 多线程可以并行 I/O

答案

  • 线程适合 I/O 密集型任务
    • 网络请求(HTTP 请求、数据库查询)
    • 文件读写
    • 网络爬虫
    • Web 服务器处理请求
import threadingimport requestsdeffetch_url(url):    response = requests.get(url)return response.textthreads = []for url in urls:    t = threading.Thread(target=fetch_url, args=(url,))    threads.append(t)    t.start()
  • 不适合:大量计算任务(受 GIL 限制)
  • 特点:轻量级、共享内存、切换开销小

题目 77:什么是 GIL?

考点

  • Global Interpreter Lock
  • GIL 的影响
  • Python 并发机制

解析思路

  • GIL 是 Python 的解释器锁
  • 保证同一时刻只有一个线程执行 Python 字节码
  • 影响 CPU 密集型任务

答案

  • GIL(全局解释器锁):CPython 的机制,同一时刻只允许一个线程执行 Python 字节码。
import threadingimport timedefcpu_task():    count = 0for i in range(100000000):        count += 1return count# CPU 密集型:多线程无效t1 = threading.Thread(target=cpu_task)t2 = threading.Thread(target=cpu_task)t1.start(); t2.start()  # 总时间 ≈ 单线程!
  • 影响
    • CPU 密集型任务:多线程无法并行,反而增加开销
    • I/O 密集型任务:多线程仍然有效(等待 I/O 时释放 GIL)
  • 解决方案:多进程(multiprocessing)、异步(asyncio)、或使用无 GIL 的 Python(PyPy)

题目 78:进程适合什么场景?

考点

  • 多进程 vs 多线程
  • CPU 密集型任务
  • 进程池

解析思路

  • 进程绕过 GIL
  • 适合 CPU 密集型
  • 适合多核并行

答案

  • 进程适合 CPU 密集型任务
    • 科学计算
    • 数据处理
    • 图像处理
    • 机器学习训练
from multiprocessing import Pooldefcpu_task(n):return sum(i**2for i in range(n))if __name__ == "__main__":with Pool(4as p:  # 4 个进程        results = p.map(cpu_task, [10000000] * 8)
  • 特点
    • 绕过 GIL,真正并行
    • 进程间隔离,需要 IPC
    • 比线程更重的资源消耗
  • 选择:I/O 密集型用线程,CPU 密集型用多进程

题目 79:为什么 Windows 下多进程要写 if name == "main"?

考点

  • Windows 的进程创建机制
  • 跨平台兼容性
  • spawn vs fork

解析思路

  • Windows 使用 spawn 方式创建进程
  • 会重新执行模块代码
  • 需要保护创建进程的代码

解析思路

  • Windows 使用 spawn 方式:创建进程时会重新导入模块、执行所有顶层代码
  • Linux 使用 fork 方式:子进程继承父进程状态
from multiprocessing import Processdefworker():    print("Worker")if __name__ == "__main__":  # Windows 必须!    p = Process(target=worker)    p.start()
  • 如果没有保护
    • Windows 上会无限递归创建子进程
    • 子进程也会执行 Process(...) 创建新的子进程
  • 最佳实践:所有 multiprocessing 代码都放在 if __name__ == "__main__" 下

题目 80:协程适合什么场景?

考点

  • 协程的特点
  • I/O 密集型任务
  • 高并发场景

解析思路

  • 协程是用户态轻量级线程
  • 单线程内实现并发
  • 适合高并发 I/O 场景

答案

  • 协程适合高并发 I/O 任务
    • Web 服务器
    • 爬虫
    • 实时通信
    • 数据库连接池
import asyncioasyncdeffetch(url):asyncwith aiohttp.ClientSession() as session:asyncwith session.get(url) as response:returnawait response.text()asyncdefmain():    urls = [...]    tasks = [fetch(url) for url in urls]    results = await asyncio.gather(*tasks)
  • 优势

    • 单线程内实现并发
    • 无需上下文切换
    • 适合超高并发(数万连接)
  • 对比

    方案
    适用场景
    并发数
    线程
    I/O 密集(低并发)
    百级
    协程
    I/O 密集(高并发)
    万级
    进程
    CPU 密集
    CPU 核数

题目 81:async 和 await 是什么?

考点

  • async/await 语法
  • 协程函数
  • 异步编程

解析思路

  • async 定义协程函数
  • await 等待协程完成
  • 事件循环驱动

答案

  • async def 定义协程函数await 等待协程对象
import asyncio# 定义协程函数asyncdeffetch_data():    print("Fetching...")await asyncio.sleep(1)  # 模拟 I/Oreturn"data"# 运行协程asyncdefmain():    result = await fetch_data()  # 等待协程完成    print(result)asyncio.run(main())
  • 关键点
    • async def 定义的是协程函数,返回协程对象
    • await 只能在 async def 函数内使用
    • asyncio.run() 创建事件循环并运行
    • await 会让出控制权,允许其他协程运行

题目 82:如何并发运行多个协程?

考点

  • asyncio.gather
  • asyncio.create_task
  • asyncio.wait

解析思路

  • gather 并发等待多个协程
  • create_task 调度协程
  • 等待方式

答案

import asyncioasyncdeftask(id):await asyncio.sleep(0.5)returnf"Task {id} done"asyncdefmain():# 方式一:gather(推荐)    results = await asyncio.gather(        task(1),        task(2),        task(3)    )    print(results)  # ['Task 1 done', 'Task 2 done', 'Task 3 done']# 方式二:create_task + wait    t1 = asyncio.create_task(task(1))    t2 = asyncio.create_task(task(2))    done, pending = await asyncio.wait([t1, t2])
  • gather:等待所有协程完成,返回结果列表
  • wait:等待协程集合完成,返回 (done, pending) 集合

题目 83:time.sleep() 和 asyncio.sleep() 有什么区别?

考点

  • 阻塞 vs 协作式
  • 线程 vs 协程
  • 事件循环

解析思路

  • time.sleep() 阻塞线程
  • asyncio.sleep() 让出控制权
  • 在协程中必须用 asyncio.sleep()

答案

  • time.sleep()阻塞当前线程(线程暂停等待)
  • asyncio.sleep()挂起当前协程(让出控制权给事件循环)
import asyncioimport time# 协程中使用 time.sleep()(错误)asyncdefbad_example():    time.sleep(1)  # 阻塞整个线程,其他协程无法运行!# 协程中使用 asyncio.sleep()(正确)asyncdefgood_example():await asyncio.sleep(1)  # 挂起协程,其他协程可以运行
  • 关键区别
    • time.sleep():线程阻塞,CPU 空转
    • asyncio.sleep():协程挂起,事件循环可以切换到其他协程
  • 原则:在 async 函数中必须使用 asyncio.sleep()

题目 84:如何避免多个线程同时修改共享数据?

考点

  • 线程同步
  • Lock(锁)
  • 锁的使用

解析思路

  • 使用 threading.Lock
  • 保证同一时刻只有一个线程访问
  • 注意死锁问题

答案

  • 使用 threading.Lock 实现线程同步。
import threadingcounter = 0lock = threading.Lock()defincrement():global counterfor _ in range(1000000):with lock:  # 自动获取/释放锁            counter += 1threads = [threading.Thread(target=increment) for _ in range(4)]for t in threads:    t.start()for t in threads:    t.join()print(counter)  # 4000000
  • with lock:推荐写法,自动管理锁
  • 死锁风险:避免嵌套锁、按固定顺序获取锁

十、常用标准库与实战能力


题目 85:collections.defaultdict 有什么用?

考点

  • defaultdict
  • 字典默认值
  • 自动初始化

解析思路

  • 访问不存在的 key 时自动初始化
  • 省去手动检查
  • 常见用法

答案

  • defaultdict 在访问不存在的 key 时自动调用工厂函数创建默认值。
from collections import defaultdict# 自动创建列表dd_list = defaultdict(list)dd_list["fruits"].append("apple")dd_list["fruits"].append("banana")print(dd_list)  # {'fruits': ['apple', 'banana']}# 自动创建字典dd_dict = defaultdict(dict)dd_dict["user"]["name"] = "Alice"print(dd_dict)  # {'user': {'name': 'Alice'}}# 自动计数dd_int = defaultdict(int)dd_int["apple"] += 1print(dd_int)  # {'apple': 1}
  • 工厂函数listdictint(默认 0)、set

题目 86:deque 适合什么场景?

考点

  • deque 数据结构
  • 双端队列
  • 与 list 的对比

解析思路

  • deque 两端操作 O(1)
  • list 头部操作 O(n)
  • 适合队列、滑动窗口

答案

  • deque(双端队列)在两端操作效率高,适合队列和滑动窗口。
from collections import deque# 两端添加/删除 O(1)dq = deque([123])dq.appendleft(0)  # [0, 1, 2, 3]dq.append(4)     # [0, 1, 2, 3, 4]dq.popleft()     # 返回 0dq.pop()         # 返回 4# 滑动窗口defsliding_window_max(nums, k):    dq = deque()    result = []for i, num in enumerate(nums):while dq and nums[dq[-1]] < num:            dq.pop()        dq.append(i)if dq[0] <= i - k:            dq.popleft()if i >= k - 1:            result.append(nums[dq[0]])return result
  • 对比:list 的 insert(0, x) 和 pop(0) 是 O(n),deque 是 O(1)

题目 87:heapq 有什么用?

考点

  • 堆数据结构
  • heapq 模块
  • 优先队列

解析思路

  • 堆是特殊的完全二叉树
  • 最小堆:父节点 <= 子节点
  • heapq 提供堆操作

答案

  • heapq 提供最小堆操作。
import heapq# 创建堆heap = []heapq.heappush(heap, 5)heapq.heappush(heap, 2)heapq.heappush(heap, 8)print(heap)  # [2, 5, 8]# 弹出最小print(heapq.heappop(heap))  # 2# 堆化列表nums = [5281]heapq.heapify(nums)print(nums)  # [1, 2, 8, 5]# 最大堆:存负数max_heap = []heapq.heappush(max_heap, -5)heapq.heappush(max_heap, -2)heapq.heappush(max_heap, -8)print(-heapq.heappop(max_heap))  # 8# 优先队列deftop_k(nums, k):return heapq.nlargest(k, nums)  # 前 k 大

题目 88:json.dumps() 和 json.loads() 有什么区别?

考点

  • JSON 序列化/反序列化
  • 内存对象与 JSON 字符串
  • 使用场景

解析思路

  • dumps:Python 对象 → JSON 字符串
  • loads:JSON 字符串 → Python 对象
  • 记忆技巧

答案

  • dumps:Python 对象序列化为 JSON 字符串
  • loads:JSON 字符串反序列化为 Python 对象
import json# Python 对象 → JSON 字符串data = {"name""Alice""age"25"scores": [908588]}json_str = json.dumps(data)print(json_str)  # {"name": "Alice", "age": 25, "scores": [90, 85, 88]}# JSON 字符串 → Python 对象parsed = json.loads(json_str)print(parsed)  # {'name': 'Alice', 'age': 25, 'scores': [90, 85, 88]}# 格式化输出print(json.dumps(data, indent=2, ensure_ascii=False))
  • 记忆s 表示 string(字符串)

题目 89:如何处理 Decimal 不能直接 JSON 序列化的问题?

考点

  • JSON 序列化
  • Decimal 类型
  • 自定义编码器

解析思路

  • Decimal 是高精度小数
  • 需要自定义序列化
  • 转换为 float 或字符串

答案

import jsonfrom decimal import Decimaldata = {"price": Decimal("19.99"), "amount": Decimal("100")}# 方式一:转换为 float(可能有精度损失)defdecimal_to_float(obj):if isinstance(obj, Decimal):return float(obj)raise TypeErrorjson_str = json.dumps(data, default=decimal_to_float)print(json_str)  # {"price": 19.99, "amount": 100.0}# 方式二:转换为字符串(保持精度)defdecimal_to_str(obj):if isinstance(obj, Decimal):return str(obj)raise TypeErrorjson_str = json.dumps(data, default=decimal_to_str)print(json_str)  # {"price": "19.99", "amount": "100"}

题目 90:pathlib 相比 os.path 有什么好处?

考点

  • pathlib 模块
  • 面向对象路径操作
  • 可读性和可维护性

解析思路

  • pathlib 用面向对象方式处理路径
  • 路径操作更直观
  • 统一 Windows/Unix 路径

答案

from pathlib import Pathp = Path("project/data/file.txt")# 路径拼接(比 os.path.join 更直观)p2 = p / ".." / "backup" / p.name# 属性访问print(p.name)     # file.txtprint(p.stem)     # fileprint(p.suffix)   # .txtprint(p.parent)   # project/data# 方法print(p.exists())    # 检查存在p.mkdir(parents=True, exist_ok=True)  # 创建目录p.write_text("content")  # 写入文件# 路径规范化print(p.resolve())  # 绝对路径
  • 优势
    1. 面向对象,API 更直观
    2. 操作符重载:p / "subdir"
    3. 属性访问:p.namep.suffix
    4. 跨平台兼容

题目 91:如何读取 CSV 文件?

考点

  • csv 模块
  • 读取 CSV 的方式
  • 常见问题处理

解析思路

  • 使用 csv 模块
  • DictReader 读取为字典
  • 处理中文编码

答案

import csv# 方式一:读取为列表with open("data.csv""r", encoding="utf-8"as f:    reader = csv.reader(f)for row in reader:        print(row)# 方式二:读取为字典(推荐)with open("data.csv""r", encoding="utf-8"as f:    reader = csv.DictReader(f)for row in reader:        print(row["name"], row["age"])# 写入 CSVwith open("output.csv""w", encoding="utf-8", newline=""as f:    writer = csv.DictWriter(f, fieldnames=["name""age"])    writer.writeheader()    writer.writerow({"name""Alice""age"25})
  • 注意
    • 指定 encoding="utf-8"
    • Windows 下写入加 newline=""
    • 大文件用 csv.DictReader 更易处理

题目 92:如何记录日志?

考点

  • logging 模块
  • 日志级别
  • 配置方式

解析思路

  • logging 是标准库
  • 基本配置
  • 不同输出方式

解析思路

import logging# 基本配置logging.basicConfig(    level=logging.INFO,    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",    handlers=[        logging.FileHandler("app.log"),        logging.StreamHandler()    ])logger = logging.getLogger(__name__)logger.debug("Debug message")logger.info("Info message")logger.warning("Warning message")logger.error("Error message")
  • 日志级别(从低到高):DEBUG < INFO < WARNING < ERROR < CRITICAL
  • 最佳实践
    1. 模块级别 logger
    2. 适当使用日志级别
    3. 生产环境配置多个 handler

题目 93:如何写单元测试?

考点

  • unittest 模块
  • 测试用例
  • 断言方法

解析思路

  • unittest 是标准库
  • TestCase 类
  • 常用断言方法

答案

import unittestdefadd(a, b):return a + bclassTestAdd(unittest.TestCase):deftest_positive_numbers(self):        self.assertEqual(add(12), 3)deftest_negative_numbers(self):        self.assertEqual(add(-1-2), -3)deftest_mixed_numbers(self):        self.assertEqual(add(-12), 1)deftest_zero(self):        self.assertEqual(add(05), 5)        self.assertEqual(add(50), 5)if __name__ == "__main__":    unittest.main()
  • 常用断言
    • assertEqual(a, b):相等
    • assertTrue(x):为真
    • assertRaises(Exception):抛出异常
    • assertAlmostEqual(a, b):浮点数近似相等

题目 94:pytest.raises 怎么用?

考点

  • pytest
  • 异常测试
  • 上下文管理器

解析思路

  • pytest.raises 捕获异常
  • 使用 with 语句
  • 验证异常类型和消息

答案

import pytestdefdivide(a, b):if b == 0:raise ValueError("Cannot divide by zero")return a / b# 基本用法deftest_division_by_zero():with pytest.raises(ValueError):        divide(10)# 验证异常消息deftest_division_error_message():with pytest.raises(ValueError, match="Cannot divide by zero"):        divide(10)# 验证异常属性deftest_exception_attributes():with pytest.raises(ValueError) as exc_info:        divide(10)assert"zero"in str(exc_info.value)
  • match 参数:正则匹配异常消息

十一、性能、内存、编码规范


题目 95:如何查看对象占用内存?

考点

  • sys.getsizeof()
  • 内存占用
  • 内存分析工具

解析思路

  • sys.getsizeof 查看单个对象
  • 深度分析用 tracemalloc
  • 近似计算

答案

import sys# 查看单个对象大小print(sys.getsizeof(1))           # 28print(sys.getsizeof("hello"))     # 54print(sys.getsizeof([123]))   # 72print(sys.getsizeof({"a"1}))    # 232# 深度分析内存import tracemalloctracemalloc.start()data = [x ** 2for x in range(10000)]current, peak = tracemalloc.get_traced_memory()print(f"当前: {current / 1024:.2f} KB")print(f"峰值: {peak / 1024:.2f} KB")tracemalloc.stop()# 第三方工具:pip install pymplerfrom pympler import asizeofprint(asizeof.asizeof(data))

题目 96:如何优化大列表处理?

考点

  • 生成器表达式
  • 迭代器
  • 内存优化

解析思路

  • 避免一次性生成完整列表
  • 使用生成器
  • 使用 itertools

答案

# 问题:生成 1000000 个平方数# 不推荐:列表占用大量内存squares = [x**2for x in range(1000000)]# 推荐:生成器按需计算squares = (x**2for x in range(1000000))# 分批处理defprocess_in_chunks(data, chunk_size=1000):for i in range(0, len(data), chunk_size):yield data[i:i+chunk_size]# 使用 itertoolsfrom itertools import islicedefgenerate_squares():    i = 0whileTrue:yield i ** 2        i += 1# 取前 10 个平方数squares = islice(generate_squares(), 10)print(list(squares))  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

题目 97:浅拷贝和深拷贝有什么区别?

考点

  • 浅拷贝
  • 深拷贝
  • 引用 vs 值

解析思路

  • 浅拷贝只拷贝第一层
  • 深拷贝递归拷贝所有层
  • 适用场景

答案

import copyoriginal = [[123], [456]]# 浅拷贝:只拷贝一层shallow = copy.copy(original)shallow[0][0] = 99print(original)   # [[99, 2, 3], [4, 5, 6]],原数据被修改!# 深拷贝:递归拷贝所有层deep = copy.deepcopy(original)deep[0][0] = 88print(original)   # [[99, 2, 3], [4, 5, 6]],原数据不变# 切片是浅拷贝lst = [[12], [34]]lst_copy = lst[:]
操作
说明
适用场景
copy.copy()
浅拷贝,只拷贝第一层
不可变对象
copy.deepcopy()
深拷贝,递归所有层
可变嵌套结构
[:]
切片(浅拷贝)
简单列表

题目 98:with 为什么比手动 close() 更安全?

考点

  • 上下文管理器
  • 资源释放
  • 异常安全

解析思路

  • with 自动调用 exit
  • 即使异常也会关闭
  • 避免资源泄漏

答案

  • with 语句在任何情况下都会释放资源,即使发生异常。
# 手动关闭(不安全)f = open("file.txt""r")content = f.read()f.close()  # 如果 read() 抛异常,文件不会关闭!# with 语句(安全)with open("file.txt""r"as f:    content = f.read()# 无论是否异常,文件都会关闭# try...finally 等效f = open("file.txt""r")try:    content = f.read()finally:    f.close()  # 总是执行
  • 优势
    1. 自动释放资源
    2. 代码更简洁
    3. 异常安全

题目 99:Python 代码规范主要看什么?

考点

  • PEP 8
  • 代码规范
  • 可读性

解析思路

  • PEP 8 是官方风格指南
  • 常用规范要点
  • 工具辅助

答案

  • PEP 8 是 Python 官方代码规范指南,主要关注:
    • a = b 而不是 a=b
    • 函数周围空两行
    • 列表/字典内避免多余空格
    • 变量/函数:snake_case
    • 类:PascalCase
    • 常量:UPPER_SNAKE_CASE
    1. 命名规范
    2. 空格规范
    3. 行长度:不超过 79 字符
    4. 导入顺序:标准库 → 第三方 → 本地
    5. 注释:清晰、必要、更新
# 好的写法defcalculate_total(items, tax_rate=0.1):    subtotal = sum(item['price'for item in items)return subtotal * (1 + tax_rate)# 工具:black(格式化)、flake8(检查)、mypy(类型)
  • 工具推荐black(自动格式化)、flake8(检查)、mypy(类型检查)

题目 100:面试中如何回答"你怎么提升 Python 代码质量"?

考点

  • 代码质量意识
  • 工程实践
  • 持续改进

解析思路

  • 从多个维度回答
  • 结合实际经验
  • 展示工程能力

答案

从以下维度阐述:

  1. 代码规范

    • 遵循 PEP 8,使用 black、flake8
    • 统一命名和代码风格
    • 编写清晰的注释和文档字符串
  2. 类型提示

    • 使用 Type Hints
    • 运行 mypy 进行静态检查
    • 提高代码可读性和 IDE 支持
  3. 测试覆盖

    • 单元测试(pytest)
    • 测试覆盖率(pytest-cov)
    • TDD 开发流程
  4. 重构与设计

    • 保持函数短小、单一职责
    • 使用设计模式优化
    • 避免重复代码(DRY)
  5. 性能优化

    • 使用生成器代替列表
    • 性能分析(cProfile)
    • 选择合适的数据结构
  6. 代码审查

    • Pull Request 审查
    • 同事反馈
    • 持续改进

回答示例

"我会从规范、测试、性能三个维度提升代码质量。规范上使用 black 统一格式、flake8 检查;测试上用 pytest 做单元测试,保证覆盖率;性能上用生成器处理大数据,用 cProfile 分析瓶颈。同时保持函数短小、命名清晰,并通过 Code Review 持续改进。"

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 19:17:48 HTTP/2.0 GET : https://f.mffb.com.cn/a/494379.html
  2. 运行时间 : 0.228067s [ 吞吐率:4.38req/s ] 内存消耗:5,148.27kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=4671f09a40466f3b94b4486170c58959
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000344s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000582s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000256s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.001612s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000636s ]
  6. SELECT * FROM `set` [ RunTime:0.022849s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000726s ]
  8. SELECT * FROM `article` WHERE `id` = 494379 LIMIT 1 [ RunTime:0.002142s ]
  9. UPDATE `article` SET `lasttime` = 1783077468 WHERE `id` = 494379 [ RunTime:0.010819s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000450s ]
  11. SELECT * FROM `article` WHERE `id` < 494379 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.015497s ]
  12. SELECT * FROM `article` WHERE `id` > 494379 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.001365s ]
  13. SELECT * FROM `article` WHERE `id` < 494379 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.046020s ]
  14. SELECT * FROM `article` WHERE `id` < 494379 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.018043s ]
  15. SELECT * FROM `article` WHERE `id` < 494379 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.036868s ]
0.229632s