前言
很多Python开发者习惯了“能跑就行”的思路,但项目上线后,代码冗余、运行慢、内存占用高、可读性差、难以维护等问题会让业务寸步难行。同样的功能,新手代码可能耗时10秒、吃满内存,而经过工程优化的代码能毫秒级响应、优雅简洁。本文整理7个生产级Python优化技巧,覆盖循环、内存、字典、异常、日志和资源管理,每个点都附带错误案例与优化源码,帮助彻底摆脱新手写法。
01 用元组解包 + 短路判断消灭嵌套
新手常见多层if嵌套,可读性差且易埋bug:
- user_info = {"name": "张三", "age": 25, "gender": "male"}
- if user_info:
- if "name" in user_info:
- if "age" in user_info:
- print(f"用户姓名:{user_info['name']},年龄:{user_info['age']}")
- else:
- print("用户信息为空")
- else:
- print("用户信息为空")
复制代码
优化思路:用 all() 批量校验键存在性,再通过元组解包一次性赋值。
- user_info = {"name": "张三", "age": 25, "gender": "male"}
- if user_info and all(k in user_info for k in ["name", "age"]):
- name, age = user_info["name"], user_info["age"]
- print(f"用户姓名:{name},年龄:{age}")
- else:
- print("用户信息缺失或为空")
复制代码
核心原理:all() 批量判断键是否存在,元组解包减少变量赋值,彻底消灭多层嵌套,代码扁平化。
02 filter + map 高阶函数替代手写循环
大数据量下手写for循环并手动append,性能很差。Python内置的filter、map由C实现,效率远高于纯Python循环。
新手写法:
- nums = [1, 2, 3, 4, 5, 6, 7, 8]
- res = []
- for num in nums:
- if num % 2 == 0:
- res.append(num ** 2)
- print(res)
复制代码
优化写法(链式调用):
- nums = [1, 2, 3, 4, 5, 6, 7, 8]
- res = list(map(lambda x: x ** 2, filter(lambda x: x % 2 == 0, nums)))
- print(res) # [4, 16, 36, 64]
复制代码
适用场景:超大数据量时,优先使用高阶函数或列表推导式,避免手动for+append,性能可提升30%-80%。
03 用生成器替代列表,防止内存暴涨
新手处理百万级数据时习惯先用列表存全部结果,导致内存溢出。生成器采用惰性计算,一次只生成一条数据,内存占用极低。
新手写法(内存爆炸):
- def get_data():
- res = []
- for i in range(1000000):
- res.append(i * 2)
- return res
- data = get_data()
复制代码
优化写法(yield生成器):
- def get_data():
- for i in range(1000000):
- yield i * 2
- for item in get_data():
- if item > 1000:
- break
- print(item)
复制代码
适用场景:日志读取、大数据遍历、文件批量解析、数据库批量查询。
04 字典取值用 get() 避免 KeyError
新手直接用 dict[key] 获取值,键不存在时程序崩溃。用 get() 可以优雅地返回默认值。
新手危险写法:
- user = {"name": "李四", "age": 28}
- address = user["address"] # KeyError!
复制代码
优化写法:
- user = {"name": "李四", "age": 28}
- address = user.get("address", "未知地址")
- print(address) # 未知地址
- user.setdefault("phone", "未知手机号")
- print(user)
复制代码
进阶:复杂嵌套字典可封装递归取值函数,彻底解决多层键缺失问题。
05 精准捕获异常,拒绝裸 except
新手常用 except: 捕获所有异常,隐藏真正的bug,线上问题难以定位。应优先捕获具体异常类型,最后用 Exception 兜底并记录日志。
新手不规范写法:
- def divide(a, b):
- try:
- return a / b
- except:
- return "执行失败"
复制代码
优化写法:
- def divide(a, b):
- try:
- return a / b
- except ZeroDivisionError:
- print("【参数异常】除数不能为0")
- return None
- except TypeError:
- print("【类型异常】参数必须为数字")
- return None
- except Exception as e:
- print(f"【未知异常】{str(e)}")
- return None
- print(divide(10, 0))
复制代码
规范:线上所有异常必须记录详细日志,便于溯源。
06 用 logging 替换 print,分级输出日志
新手全程用 print() 打印日志,没有时间戳、级别、行号,线上排查完全失效。以下是一套可直接复用的日志配置模板:
- import logging
- logging.basicConfig(
- level=logging.INFO,
- format="%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s",
- datefmt="%Y-%m-%d %H:%M:%S"
- )
- logging.debug("调试信息:仅开发环境展示")
- logging.info("正常业务日志:接口调用、数据处理")
- logging.warning("警告信息:参数异常、数据缺失")
- logging.error("错误信息:程序报错、接口失败")
复制代码
核心优势:自带时间、代码行号、级别,支持文件落地和按天切割。
07 用 with 上下文管理器管控资源
文件、数据库连接、网络请求等资源操作,新手容易忘记 close(),异常时更会漏关,造成资源泄漏。with 语句自动申请和释放资源,异常时也能回收。
新手资源泄漏写法:
- f = open("test.txt", "w", encoding="utf-8")
- f.write("Python工程化优化")
- f.close() # 如果之前异常中断,close不会执行
复制代码
优化写法:
- with open("test.txt", "w", encoding="utf-8") as f:
- f.write("Python工程化优化,拒绝资源泄露")
- print("文件写入完成")
复制代码
拓展:数据库连接、Redis连接、HTTP请求均可自定义上下文管理器,统一资源管控。
总结
新手重功能,高手重性能、规范、稳定性和可维护性。上文7个技巧核心:
- 代码扁平化(元组解包 + all)
- 循环优化(filter / map)
- 内存优化(生成器)
- 字典取值(get())
- 异常处理(精准捕获 + 日志记录)
- 日志工程化(logging 替代 print)
- 资源管控(with 上下文管理器)
熟练掌握这些,就能写出企业级可落地、高性能的 Python 代码。 |