如何在复杂场景下高效编写Python字典推导式?
优化字典推导式避免重复计算的技巧
你遇到的这种场景太常见了——用字典推导式时不小心重复调用了耗时的函数,平白浪费了效率。先还原下你的使用场景:
假设我们有数据库文件名列表,还有一个生成报告的耗时函数:
db_file_names = ['f1', 'f2'] # list of database files def make_report(filename): # 读取数据库并生成报告对象(耗时操作) return report_object
我们的目标是构建一个键为db_version、值为num_tables的字典,所需数据都包含在报告对象里。
最初的低效写法
你一开始写的推导式虽然能正常运行,但每个数据库文件会被调用两次make_report,效率极低:
d = { make_report(filename).db_version: make_report(filename).num_tables for filename in db_file_names }
你已尝试的改进方法
你自己已经想到了两种可行的优化方案:
- 方法一:临时存储报告列表
先一次性生成所有报告对象,再用推导式构建字典,确保每个文件只被处理一次:reports = [make_report(filename) for filename in db_file_names] d = {r.db_version: r.num_tables for r in reports} - 方法二:生成器适配器
写一个生成器函数提前处理每个文件,返回键值对元组,再转成字典:def gen_data(): for filename in db_file_names: report = make_report(filename) yield report.db_version, report.num_tables d = {dat[0]: dat[1] for dat in gen_data()}
你还试过这种嵌套循环的写法,但觉得不够优雅:
d = { report.db_version: report.num_tables for filename in db_file_names for report in [make_report(filename), ] }
更优的解决方案推荐
针对这种场景,其实有更简洁高效的写法,分两种情况:
1. Python 3.8+(推荐):利用海象运算符:=
海象运算符允许我们在推导式内部直接赋值,完美解决重复调用的问题,同时保持推导式的简洁性:
d = { (report := make_report(filename)).db_version: report.num_tables for filename in db_file_names }
这里report := make_report(filename)会把生成的报告对象赋值给report,之后我们可以直接复用这个对象的属性,每个文件只会调用一次make_report。
2. 低版本Python:用map配合小函数
如果你的Python版本低于3.8,没法用海象运算符,那么可以用map配合一个小函数来封装逻辑,同样简洁高效:
def extract_key_value(filename): report = make_report(filename) return report.db_version, report.num_tables d = dict(map(extract_key_value, db_file_names))
这个写法把“生成报告+提取键值”的逻辑封装在一个小函数里,可读性强,同时每个文件只处理一次。
总结
- Python 3.8及以上:优先选择海象运算符版的字典推导式,兼顾简洁性和效率
- 低版本Python:临时列表存储报告或者map+小函数都是不错的选择,前者更直观,后者更紧凑
内容的提问来源于stack exchange,提问作者lesnik
相关产品推荐
相关产品推荐

