如何优化Python列表推导式?现有写法存在变量赋值不一致问题
问题描述
假设我们有如下列表:
input_list = [{'a': 1, 'b': 2}, {'a': 3, 'b': 5}]
需要基于该列表生成output_list,原循环实现如下:
output_list = [] for dic in input_list: new_dic = {} ab_sum = sum([dic['a'], dic['b']]) if ab_sum % 2 == 0: new_dic['c'] = ab_sum new_dic['d'] = ab_sum ** 2 new_dic['e'] = ab_sum ** 4 output_list.append(new_dic)
运行结果为:
[{'c': 8, 'd': 64, 'e': 4096}]
由于实际场景中字典规模更大,循环写法显得繁琐,尝试用列表推导式实现:
output_list = [{'c': ab_sum, 'd': (ab_sq:= ab_sum **2), 'e': ab_sq **2} for dic in input_list if (ab_sum:=sum([dic['a'], dic['b']])) % 2 == 0]
但这种写法在过滤条件和字典内部都用到了赋值表达式,感觉不够一致,想知道有没有更优雅的解决方案,或者是不是自己过度思考了?
优雅的实现方案
方式1:提取辅助函数(推荐)
把计算逻辑和新字典生成逻辑封装成单独函数,既能简化列表推导式,又能提升代码可读性和可维护性,尤其适合逻辑复杂、字典规模大的场景:
def process_item(dic): ab_sum = sum([dic['a'], dic['b']]) if ab_sum % 2 != 0: return None ab_sq = ab_sum ** 2 return {'c': ab_sum, 'd': ab_sq, 'e': ab_sq ** 2} output_list = [result for result in (process_item(dic) for dic in input_list) if result is not None]
方式2:前置生成器计算中间值
先用生成器表达式算出所有符合条件的ab_sum,再基于这些值生成目标字典,推导式逻辑更线性:
output_list = [ {'c': s, 'd': s**2, 'e': s**4} for s in (sum([dic['a'], dic['b']]) for dic in input_list) if s % 2 == 0 ]
如果输入字典的键只有a和b,还可以把sum([dic['a'], dic['b']])简化为sum(dic.values())。
方式3:统一赋值表达式的使用位置
如果偏好使用赋值表达式,可以把中间变量的计算放在推导式的循环环节,避免在条件和字典内部分散赋值:
output_list = [ {'c': s, 'd': s_sq, 'e': s_sq**2} for dic in input_list if (s := sum([dic['a'], dic['b']])) % 2 == 0 for s_sq in [s**2] ]
关于“过度思考”的疑问
其实你的原列表推导式本身是可行的,但如果追求更清晰的代码结构,上面几种方案会更优。尤其是辅助函数的写法,在后续需求变更时(比如新增字段、修改计算逻辑),调整起来会更方便,不算过度思考。
内容的提问来源于stack exchange,提问作者sierra_papa
相关产品推荐
相关产品推荐

