【Python 进阶之路】第1讲 | 性能优化与调优实战:让你的代码飞起来
Python 版本:Python 3.12+
开发工具:PyCharm / VS Code
操作系统:Windows / macOS / Linux (通用)
1. 说在前面:为什么你的代码总是"慢半拍"?
兄弟们,恭喜你完成了基础系列的学习!现在你已经能写出能跑的代码了。但是,能跑和跑得快,中间隔着一道鸿沟。
你有没有遇到过这些场景:
- 你的 API 接口响应时间超过 3 秒,用户开始骂娘了。
- 你的数据处理脚本跑了一晚上还没结束,内存却已经爆了。
- 你的爬虫程序越跑越慢,最后直接卡死。
这些问题,不是你代码逻辑写错了,而是你不懂性能优化。今天这一讲,咱们就来聊聊怎么让你的代码从"老爷车"变成"法拉利"。
补充:Python 之父 Guido van Rossum 的设计哲学是"优雅、明确、简单",但这不意味着 Python 代码不能高效运行。
2. 性能分析工具:先诊断,再开药
很多新手优化代码的方式是"瞎猜":我觉得这里慢,就改改那里。这是大忌!性能优化讲究的是数据驱动,你得先知道哪里慢,才能对症下药。
2.1 cProfile:Python 自带的"体检中心"
cProfile 是 Python 标准库里的性能分析工具,它能告诉你每个函数被调用了多少次、花了多少时间。
import cProfile import time defslow_function(): time.sleep(0.1)return"我是个慢函数"deffast_function():return"我是个快函数"defmain():for _ inrange(10): slow_function()for _ inrange(100): fast_function()if __name__ =="__main__": cProfile.run("main()", sort="cumulative")运行这段代码,你会看到类似这样的输出:
206 function calls in 1.007 seconds Ordered by: cumulative time ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 1.007 1.007 <string>:1(<module>) 1 0.000 0.000 1.007 1.007 test.py:9(main) 10 0.000 0.000 1.006 0.101 test.py:4(slow_function) 10 1.006 0.101 1.006 0.101 {built-in method time.sleep} 100 0.000 0.000 0.000 0.000 test.py:7(fast_function) 老司机解读:
| 字段 | 含义 | 说明 |
|---|---|---|
ncalls | 调用次数 | 函数被调用的次数 |
tottime | 自身耗时 | 函数本身花费的时间(不包括调用的其他函数) |
cumtime | 累计耗时 | 函数累计花费的时间(包括调用的其他函数) |
percall | 单次平均 | 每次调用的平均时间 |
从这个结果可以看出,slow_function 是罪魁祸首,它花了 1.006 秒,占了总时间的 99% 以上。
2.2 line_profiler:逐行分析的神器
cProfile 只能告诉你哪个函数慢,但函数里面具体哪一行慢呢?这时候就需要 line_profiler 了。
首先安装它:
pip install line_profiler 然后这样使用:
from line_profiler import LineProfiler import time defprocess_data(): data =[]for i inrange(10000): data.append(i *2) result =[]for item in data: result.append(item **2)return result lp = LineProfiler() lp_wrapper = lp(process_data) lp_wrapper() lp.print_stats()输出结果会告诉你每一行代码的执行时间:
Timer unit: 1e-07 s Total time: 0.015 s File: test.py Function: process_data at line 4 Line # Hits Time Per Hit % Time Line Contents ============================================================== 4 def process_data(): 5 1 5.0 5.0 0.0 data = [] 6 10001 35000.0 3.5 23.3 for i in range(10000): 7 10000 25000.0 2.5 16.7 data.append(i * 2) 8 9 1 2.0 2.0 0.0 result = [] 10 10001 30000.0 3.0 20.0 for item in data: 11 10000 55000.0 5.5 36.7 result.append(item ** 2) 12 13 1 5.0 5.0 0.0 return result 一眼看穿:第 11 行的 item ** 2 操作花了 36.7% 的时间,是性能瓶颈。
2.3 memory_profiler:内存泄漏的"照妖镜"
有时候你的程序慢不是因为 CPU,而是因为内存不够用,频繁触发垃圾回收。memory_profiler 可以帮你监控内存使用情况。
pip install memory_profiler from memory_profiler import profile @profiledefcreate_large_list(): large_list =[i for i inrange(1000000)]return large_list if __name__ =="__main__": create_large_list()运行后会输出每一行的内存变化:
Line # Mem usage Increment Occurrences Line Contents ============================================================= 3 38.1 MiB 38.1 MiB 1 @profile 4 def create_large_list(): 5 76.5 MiB 38.4 MiB 1000003 large_list = [i for i in range(1000000)] 6 76.5 MiB 0.0 MiB 1 return large_list 避坑小贴士
如果你发现某行代码的内存增量异常大,而且一直不释放,那就要警惕内存泄漏了。
3. 常见性能瓶颈与优化方案
知道了怎么分析性能,接下来咱们聊聊常见的性能瓶颈和对应的优化方案。
3.1 循环里的字符串拼接
错误示范:
defbad_concat(items): result =""for item in items: result +=str(item)return result 问题所在:字符串是不可变对象,每次 += 都会创建一个新的字符串对象,然后复制旧内容。如果你拼接 10000 次,就会创建 10000 个中间对象。
正确做法:
defgood_concat(items):return"".join(str(item)for item in items)性能对比:
import time items =list(range(100000)) start = time.time() bad_concat(items)print(f"bad_concat: {time.time()- start:.3f}s") start = time.time() good_concat(items)print(f"good_concat: {time.time()- start:.3f}s")
| 方法 | 执行时间 | 性能提升 |
|---|---|---|
bad_concat | 2.156s | 基准 |
good_concat | 0.012s | 180x |
快了将近 180 倍!这就是算法选择的重要性。
3.2 列表查找 vs 字典查找
错误示范:
deffind_in_list(target, items):return target in items items =list(range(100000)) find_in_list(99999, items)问题所在:列表的 in 操作是 O(n) 复杂度,需要从头遍历到尾。
正确做法:
deffind_in_dict(target, items_dict):return target in items_dict items_dict ={i:Truefor i inrange(100000)} find_in_dict(99999, items_dict)字典的 in 操作是 O(1) 复杂度,因为它基于哈希表实现。
性能对比:
import time items_list =list(range(100000)) items_dict ={i:Truefor i inrange(100000)} start = time.time()for i inrange(1000): find_in_list(99999, items_list)print(f"列表查找 1000 次: {time.time()- start:.3f}s") start = time.time()for i inrange(1000): find_in_dict(99999, items_dict)print(f"字典查找 1000 次: {time.time()- start:.3f}s")
| 数据结构 | 1000次查找时间 | 时间复杂度 |
|---|---|---|
| 列表 (List) | 0.234s | O(n) |
| 字典 (Dict) | 0.000s | O(1) |
老司机建议:如果你需要频繁判断某个元素是否存在,用集合(set)或字典,别用列表。
3.3 全局变量 vs 局部变量
Python 访问局部变量比全局变量快得多,因为局部变量存储在固定大小的数组中,而全局变量存储在字典中。
错误示范:
import math defcompute_with_global(n): result =0for i inrange(n): result += math.sqrt(i)return result 正确做法:
import math defcompute_with_local(n): sqrt = math.sqrt result =0for i inrange(n): result += sqrt(i)return result 性能对比:
| 变量类型 | 执行时间 (100万次) | 性能提升 |
|---|---|---|
| 全局变量 | 0.187s | 基准 |
| 局部变量 | 0.156s | 1.2x |
虽然差距不大,但在高频调用的场景下,积少成多,效果还是很明显的。
4. 时间复杂度与空间复杂度实战
性能优化的核心是理解算法复杂度。咱们用几个经典案例来讲解。
4.1 大 O 表示法速记
| 复杂度 | 名称 | 示例 | 数据规模 10⁴ 时的操作次数 |
|---|---|---|---|
| O(1) | 常数 | 字典查找、数组索引 | 1 |
| O(log n) | 对数 | 二分查找 | ~14 |
| O(n) | 线性 | 遍历列表 | 10,000 |
| O(n log n) | 线性对数 | 快速排序、归并排序 | ~140,000 |
| O(n²) | 平方 | 双重循环、冒泡排序 | 100,000,000 |
| O(2ⁿ) | 指数 | 递归斐波那契(无缓存) | 天文数字 |
4.2 实战案例:两数之和
问题:给定一个列表和目标值,找出列表中两个数,使它们的和等于目标值。
暴力解法(O(n²)):
deftwo_sum_slow(nums, target): n =len(nums)for i inrange(n):for j inrange(i +1, n):if nums[i]+ nums[j]== target:return[i, j]return[]优化解法(O(n)):
deftwo_sum_fast(nums, target): seen ={}for i, num inenumerate(nums): complement = target - num if complement in seen:return[seen[complement], i] seen[num]= i return[]性能对比:
import time import random nums =[random.randint(1,10000)for _ inrange(10000)] target =15000 start = time.time() result = two_sum_slow(nums, target)print(f"暴力解法: {time.time()- start:.3f}s, 结果: {result}") start = time.time() result = two_sum_fast(nums, target)print(f"优化解法: {time.time()- start:.3f}s, 结果: {result}")
| 算法 | 执行时间 | 时间复杂度 |
|---|---|---|
| 暴力解法 | 0.456s | O(n²) |
| 优化解法 | 0.001s | O(n) |
一句话总结:用空间换时间,把 O(n²) 降到了 O(n)。
5. 内存泄漏排查与解决
内存泄漏是 Python 程序的隐形杀手。它不会让你的程序立刻崩溃,但会让你的程序越跑越慢,最终被系统杀掉。
5.1 常见的内存泄漏场景
场景一:全局列表无限增长
cache =[]defadd_to_cache(item): cache.append(item)这个 cache 永远不会被清理,会一直增长直到内存爆满。
解决方案:使用 functools.lru_cache 或者手动限制大小。
from functools import lru_cache @lru_cache(maxsize=1000)defexpensive_function(n):return n **2场景二:循环引用
classNode:def__init__(self): self.ref =None a = Node() b = Node() a.ref = b b.ref = a a 和 b 互相引用,引用计数永远不会归零,导致内存无法释放。
解决方案:Python 的垃圾回收器(GC)会处理循环引用,但如果你手动关闭了 GC,就会出问题。
import gc gc.collect()场景三:闭包捕获大对象
defcreate_closure(): large_data =[i for i inrange(1000000)]definner():returnlen(large_data)return inner func = create_closure()inner 函数捕获了 large_data,即使 create_closure 执行完毕,large_data 也不会被释放。
解决方案:如果不需要 large_data,就在闭包外清理它。
5.2 使用 objgraph 定位内存泄漏
objgraph 是一个强大的工具,可以帮你可视化对象引用关系。
pip install objgraph import objgraph x =[1,2,3] y =[x, x, x] objgraph.show_refs([y], filename='refs.png')这会生成一张图片,显示 y 引用了哪些对象。
6. 高级优化技巧
6.1 使用 slots 减少内存占用
默认情况下,Python 类的每个实例都有一个 __dict__ 来存储属性,这很耗内存。使用 __slots__ 可以显著减少内存占用。
# 普通类classRegularUser:def__init__(self, name, age, email): self.name = name self.age = age self.email = email # 使用 __slots__classSlotUser: __slots__ =['name','age','email']def__init__(self, name, age, email): self.name = name self.age = age self.email = email 内存对比:
import sys regular_users =[RegularUser(f"User{i}", i,f"user{i}@example.com")for i inrange(10000)] slot_users =[SlotUser(f"User{i}", i,f"user{i}@example.com")for i inrange(10000)]print(f"RegularUser 内存: {sys.getsizeof(regular_users[0])} bytes")print(f"SlotUser 内存: {sys.getsizeof(slot_users[0])} bytes")
| 类类型 | 单个实例内存 | 10000 实例总内存 |
|---|---|---|
| RegularUser | ~152 bytes | ~1.5 MB |
| SlotUser | ~56 bytes | ~560 KB |
内存对比详细数据:
| 类类型 | 单个实例内存 | 1000 实例 | 10000 实例 | 100000 实例 |
|---|---|---|---|---|
| RegularUser | ~152 bytes | ~148 KB | ~1.5 MB | ~14.5 MB |
| SlotUser | ~56 bytes | ~55 KB | ~560 KB | ~5.4 MB |
| 内存节省 | 63% | 63% | 63% | 63% |
为什么 __slots__ 能节省内存?
普通类使用 __dict__ 存储属性,每个实例都有一个独立的字典对象,开销很大。而 __slots__ 预先声明了固定属性,使用固定大小的数组存储,避免了字典的开销。
完整的性能测试代码
import sys import time import tracemalloc # 普通类classRegularUser:def__init__(self, name, age, email): self.name = name self.age = age self.email = email # 使用 __slots__classSlotUser: __slots__ =['name','age','email']def__init__(self, name, age, email): self.name = name self.age = age self.email = email deftest_memory():"""内存占用测试"""print("=== 内存占用测试 ===")# 使用 tracemalloc 获取更准确的内存数据 tracemalloc.start() regular_users =[RegularUser(f"User{i}", i,f"user{i}@example.com")for i inrange(100000)] current1, peak1 = tracemalloc.get_traced_memory() tracemalloc.stop() tracemalloc.start() slot_users =[SlotUser(f"User{i}", i,f"user{i}@example.com")for i inrange(100000)] current2, peak2 = tracemalloc.get_traced_memory() tracemalloc.stop()print(f"RegularUser 单实例: {sys.getsizeof(regular_users[0])} bytes")print(f"SlotUser 单实例: {sys.getsizeof(slot_users[0])} bytes")print(f"普通类总内存: {current1 /1024/1024:.2f} MB")print(f"优化类总内存: {current2 /1024/1024:.2f} MB")print(f"内存节省: {(1- current2/current1)*100:.1f}%")deftest_access_speed():"""属性访问速度测试"""print("\n=== 属性访问速度测试 ===") regular_users =[RegularUser(f"User{i}", i,f"user{i}@example.com")for i inrange(10000)] slot_users =[SlotUser(f"User{i}", i,f"user{i}@example.com")for i inrange(10000)]# 测试读取速度 start = time.time()for user in regular_users: _ = user.name _ = user.age _ = user.email regular_time = time.time()- start start = time.time()for user in slot_users: _ = user.name _ = user.age _ = user.email slot_time = time.time()- start print(f"RegularUser 访问时间: {regular_time:.4f}s")print(f"SlotUser 访问时间: {slot_time:.4f}s")print(f"访问速度提升: {(regular_time/slot_time -1)*100:.1f}%")if __name__ =="__main__": test_memory() test_access_speed()运行结果示例:
=== 内存占用测试 === RegularUser 单实例: 152 bytes SlotUser 单实例: 56 bytes 普通类总内存: 14.52 MB 优化类总内存: 5.37 MB 内存节省: 63.0% === 属性访问速度测试 === RegularUser 访问时间: 0.0015s SlotUser 访问时间: 0.0012s 访问速度提升: 25.0% 避坑小贴士
__slots__ 的适用场景:
| 场景 | 是否推荐使用 | 说明 |
|---|---|---|
| 需要创建大量实例的类 | 推荐 | 内存节省效果显著 |
| 内存敏感的应用(如爬虫、数据处理) | 推荐 | 降低内存占用 |
| 属性固定的数据类 | 推荐 | 类似 C 语言的结构体 |
| 需要动态添加属性的类 | 不推荐 | 会失去灵活性 |
| 多重继承场景 | 谨慎使用 | 需要处理属性冲突 |
__slots__ 的限制与注意事项:
- 失去了
__dict__的灵活性- 无法使用
vars(obj)获取所有属性 - 无法序列化为 JSON(需要自定义方法)
- 无法使用
多重继承时的属性冲突
classA: __slots__ =['a']classB: __slots__ =['b']classC(A, B):# 多重继承 __slots__ =['c']# 需要显式声明所有父类的 slots不能动态添加新属性(除非在 __slots__ 中声明)
classUser: __slots__ =['name'] u = User() u.name ="张三"# 正常 u.age =20# AttributeError: 'User' object has no attribute 'age'最佳实践:
classDataRecord:""" 使用 __slots__ 的数据记录类 适用于:大量数据对象的存储 """ __slots__ =['id','name','value','timestamp','_initialized']def__init__(self,id, name, value, timestamp): self.id=id self.name = name self.value = value self.timestamp = timestamp self._initialized =Truedef__repr__(self):returnf"DataRecord(id={self.id}, name={self.name})"defto_dict(self):"""转换为字典,便于序列化"""return{'id': self.id,'name': self.name,'value': self.value,'timestamp': self.timestamp }7. Python 3.12+ 性能改进新特性
Python 3.12 带来了许多性能改进,了解这些新特性可以帮助我们写出更高效的代码。
7.1 核心性能提升
| 特性 | Python 3.11 | Python 3.12+ | 提升幅度 |
|---|---|---|---|
| 函数调用开销 | 基准 | 优化后 | 约 15% |
| 字符串处理 | 基准 | 优化后 | 约 20% |
| 字典操作 | 基准 | 优化后 | 约 10% |
| 列表推导式 | 基准 | 优化后 | 约 10% |
| 启动时间 | 基准 | 优化后 | 约 10% |
7.2 新特性对性能优化的影响
1. 改进的 f-string 解析
Python 3.12 重写了 f-string 的解析器,性能更好,错误提示更清晰:
# Python 3.12+ 中 f-string 性能更好 name ="Python" version =3.12# 这种写法在 3.12+ 中更高效 message =f"{name}{version} 性能更优"# 甚至可以嵌套更复杂的表达式 result =f"{(x :=10)+(y :=20)=}"# 输出: (x := 10) + (y := 20) = 302. 类型注解的性能改进
Python 3.12 优化了类型注解的处理,运行时开销更低:
from typing import List, Dict, Optional # Python 3.12+ 中类型注解不会显著影响性能classDataProcessor:defprocess(self, items: List[Dict[str, Optional[int]]])-> List[int]:return[item.get("value",0)for item in items if item]3. 新的 typing 特性
from typing import override, TypedDict # Python 3.12+ 支持 override 装饰器classBase:defmethod(self)->int:return0classDerived(Base):@override# 明确标记重写,帮助 IDE 和类型检查器defmethod(self)->int:return1# TypedDict 的新语法(更简洁)classMovie(TypedDict): name:str year:int7.3 利用 Python 3.12+ 特性优化代码
示例:使用新的异常处理语法
# Python 3.12+ 支持更清晰的异常组处理import asyncio asyncdefmain():try:asyncwith asyncio.TaskGroup()as tg: tg.create_task(task1()) tg.create_task(task2())except* ValueError as eg:# 处理一组 ValueErrorfor error in eg.exceptions:print(f"Value error: {error}")except* TypeError as eg:# 处理一组 TypeErrorfor error in eg.exceptions:print(f"Type error: {error}")性能建议:
- 升级到 Python 3.12+:享受原生性能提升
- 使用新的语法特性:f-string、类型注解等新语法更高效
- 关注标准库优化:许多内置模块在 3.12 中都有性能改进
- 使用 asyncio.TaskGroup:比手动管理任务更安全高效
8. 性能优化总结
经过这一讲的学习,我们掌握了以下性能优化技能:
| 优化技术 | 适用场景 | 性能提升 |
|---|---|---|
| cProfile/line_profiler | 定位性能瓶颈 | - |
| 字符串拼接优化 | 大量字符串操作 | 180x |
| 字典查找替代列表 | 频繁查找操作 | O(n) → O(1) |
| 局部变量优化 | 高频循环 | 1.2x |
| 算法优化 | 两数之和等经典问题 | O(n²) → O(n) |
__slots__ | 大量实例创建 | 节省 63% 内存 |
| Python 3.12+ 新特性 | 全场景 | 10-20% |
一句话总结:性能优化的核心是先测量,再优化,用数据驱动决策,而不是凭感觉。
经过这一讲的学习,我们掌握了以下性能优化技能:
| 优化技术 | 适用场景 | 性能提升 |
|---|---|---|
| cProfile/line_profiler | 定位性能瓶颈 | - |
| 字符串拼接优化 | 大量字符串操作 | 180x |
| 字典查找替代列表 | 频繁查找操作 | O(n) → O(1) |
| 局部变量优化 | 高频循环 | 1.2x |
| 算法优化 | 两数之和等经典问题 | O(n²) → O(n) |
__slots__ | 大量实例创建 | 节省 63% 内存 |
一句话总结:性能优化的核心是先测量,再优化,用数据驱动决策,而不是凭感觉。
8. 实战演练:巩固你的内功
题目 1:优化列表去重
需求:
有一个包含100万个整数的列表,需要去除重复项。
比较 set() 和 dict.fromkeys() 的性能差异。
点击查看参考答案
import time import random # 生成测试数据 data =[random.randint(1,100000)for _ inrange(1000000)]# 方法1:使用 set() start = time.time() result1 =list(set(data))print(f"set() 方法: {time.time()- start:.3f}s, 结果数量: {len(result1)}")# 方法2:使用 dict.fromkeys() start = time.time() result2 =list(dict.fromkeys(data))print(f"dict.fromkeys() 方法: {time.time()- start:.3f}s, 结果数量: {len(result2)}")# 方法3:保持顺序的优化方法defunique_ordered(items): seen =set() result =[]for item in items:if item notin seen: seen.add(item) result.append(item)return result start = time.time() result3 = unique_ordered(data)print(f"自定义方法: {time.time()- start:.3f}s, 结果数量: {len(result3)}")题目 2:内存优化实战
需求:
有一个日志处理系统,需要存储大量的日志记录。
每条日志包含:时间戳、级别、消息、来源IP。
使用 __slots__ 优化内存占用,并对比优化前后的内存使用情况。
点击查看参考答案
import sys import tracemalloc from datetime import datetime # 普通类classLogRecord:def__init__(self, timestamp, level, message, source_ip): self.timestamp = timestamp self.level = level self.message = message self.source_ip = source_ip # 使用 __slots__classLogRecordOptimized: __slots__ =['timestamp','level','message','source_ip']def__init__(self, timestamp, level, message, source_ip): self.timestamp = timestamp self.level = level self.message = message self.source_ip = source_ip deftest_memory_usage():# 测试普通类 tracemalloc.start() records1 =[LogRecord(datetime.now(),"INFO",f"Message {i}","192.168.1.1")for i inrange(100000)] current1, peak1 = tracemalloc.get_traced_memory() tracemalloc.stop()# 测试优化类 tracemalloc.start() records2 =[LogRecordOptimized(datetime.now(),"INFO",f"Message {i}","192.168.1.1")for i inrange(100000)] current2, peak2 = tracemalloc.get_traced_memory() tracemalloc.stop()print(f"普通类内存占用: {current1 /1024/1024:.2f} MB")print(f"优化类内存占用: {current2 /1024/1024:.2f} MB")print(f"内存节省: {(1- current2/current1)*100:.1f}%") test_memory_usage()题目 3:算法复杂度分析
需求:
分析以下代码的时间复杂度,并提出优化方案:
deffind_duplicates(nums): duplicates =[]for i inrange(len(nums)):for j inrange(i +1,len(nums)):if nums[i]== nums[j]and nums[i]notin duplicates: duplicates.append(nums[i])return duplicates 点击查看参考答案
原算法分析:
- 时间复杂度:O(n³) - 双重循环 +
in操作 - 空间复杂度:O(k) - k为重复元素数量
优化方案:
deffind_duplicates_optimized(nums): seen =set() duplicates =set()for num in nums:if num in seen: duplicates.add(num)else: seen.add(num)returnlist(duplicates)# 测试import random import time data =[random.randint(1,10000)for _ inrange(10000)] start = time.time() result1 = find_duplicates(data)print(f"原算法: {time.time()- start:.3f}s") start = time.time() result2 = find_duplicates_optimized(data)print(f"优化后: {time.time()- start:.3f}s")优化后复杂度:
- 时间复杂度:O(n)
- 空间复杂度:O(n)
9. 本章小结
通过本讲的学习,我们系统地掌握了 Python 性能优化的核心技能:
核心知识点回顾
1. 性能分析工具
- 使用
cProfile进行函数级性能分析 - 使用
line_profiler进行行级性能分析 - 使用
timeit进行精确计时 - 使用
tracemalloc进行内存分析
2. 代码级优化技巧
- 字符串拼接:使用
join()替代+ - 查找操作:使用
set/dict替代list - 循环优化:使用局部变量、列表推导式
- 算法优化:降低时间复杂度
3. 内存优化
- 使用
__slots__减少实例内存占用 - 使用生成器替代列表(惰性求值)
- 及时释放不再使用的对象
4. Python 3.12+ 新特性
- 原生性能提升 10-20%
- 改进的 f-string 解析
- 类型注解性能优化
- 新的异常处理语法
下一步学习建议
立即实践:
- 找一个你之前写过的项目,用
cProfile分析性能瓶颈 - 尝试用
__slots__优化一个数据类,观察内存变化 - 重构一段使用字符串拼接的代码,对比性能差异
深入学习:
- 第2讲 | 异步编程深度解析:掌握 asyncio 的核心原理
- 学习多线程与多进程编程
- 了解 Cython 和 Numba 等加速工具
推荐资源:
- Python 官方文档 - 性能优化章节
- 《Python 高性能编程》
- LeetCode 算法练习(关注复杂度分析)
10. 系列索引
写在最后:
性能优化是一门艺术,也是一门科学。记住三个原则:先测量,再优化 - 不要凭感觉优化关注瓶颈 - 80%的性能问题来自20%的代码权衡取舍 - 优化往往伴随着复杂度增加,要适可而止
如果觉得有收获,点赞、收藏、关注! 咱们下一讲聊聊异步编程!