一、核心原理:lambda + filter的搭配逻辑
- filter函数:作用是根据指定的“判断规则”,筛选可迭代对象中符合条件的元素,返回一个迭代器(需转成列表/元组查看结果)。语法:
filter(判断函数, 可迭代对象)。 - lambda函数:作为filter的第一个参数,替代需要临时定义、仅使用一次的普通判断函数(def定义),实现“一行定义筛选规则”。
- 核心优势:无需单独写def函数,代码更简洁轻量化,适合简单的条件筛选场景。
- 关键逻辑:lambda返回
True/False,filter会保留返回True的元素,过滤掉返回False的元素。
二、基础用法:单个可迭代对象的简单筛选
这是最常用的场景,针对一个列表/元组等,按单一条件筛选元素。
1. 数值类数据筛选
# 示例1:筛选列表中的偶数
nums = [1, 2, 3, 4, 5, 6, 7, 8]
# lambda x: x % 2 == 0 定义“是否为偶数”的判断规则
even_nums = list(filter(lambda x: x % 2 == 0, nums))
print(even_nums) # 输出:[2, 4, 6, 8]
# 示例2:筛选列表中大于10的数字
nums = [5, 8, 12, 9, 15, 3, 20]
big_nums = list(filter(lambda x: x > 10, nums))
print(big_nums) # 输出:[12, 15, 20]
# 示例3:筛选列表中的正数(排除0和负数)
nums = [-5, 0, 3, -2, 8, -10, 15]
positive_nums = list(filter(lambda x: x > 0, nums))
print(positive_nums) # 输出:[3, 8, 15]
# 示例4:筛选列表中在指定区间的数字(10≤x≤20)
nums = [5, 12, 18, 25, 15, 8, 20]
range_nums = list(filter(lambda x: 10 <= x <= 20, nums))
print(range_nums) # 输出:[12, 18, 15, 20]
2. 字符串类数据筛选
# 示例1:筛选列表中长度大于5的字符串
words = ["python", "lambda", "map", "filter", "data", "hello"]
long_words = list(filter(lambda x: len(x) > 5, words))
print(long_words) # 输出:['python', 'lambda', 'filter']
# 示例2:筛选列表中包含指定字符的字符串(包含"py")
words = ["python", "java", "pytest", "ruby", "pyspark"]
py_words = list(filter(lambda x: "py" in x.lower(), words)) # lower()统一转小写,避免大小写问题
print(py_words) # 输出:['python', 'pytest', 'pyspark']
# 示例3:筛选列表中非空字符串(排除空值)
strings = ["hello", "", "python", None, " ", "lambda"]
non_empty = list(filter(lambda x: x and x.strip() != "", strings)) # 排除None和空/空格字符串
print(non_empty) # 输出:['hello', 'python', 'lambda']
三、进阶用法:筛选复杂数据结构(字典列表)
实际开发中常处理字典列表(如用户信息、订单数据),lambda+filter可快速按字典的指定字段筛选数据。
# 场景:处理学生信息字典列表,按不同条件筛选
students = [
{"name": "张三", "age": 18, "score": 85, "gender": "男"},
{"name": "李四", "age": 19, "score": 92, "gender": "女"},
{"name": "王五", "age": 17, "score": 78, "gender": "男"},
{"name": "赵六", "age": 20, "score": 95, "gender": "女"},
{"name": "钱七", "age": 18, "score": 60, "gender": "男"}
]
# 示例1:筛选成绩≥80分的学生
high_score = list(filter(lambda x: x["score"] >= 80, students))
print("成绩≥80分的学生:", high_score)
# 输出:[{'name':'张三',...}, {'name':'李四',...}, {'name':'赵六',...}]
# 示例2:筛选年龄18岁且性别为男的学生
male_18 = list(filter(lambda x: x["age"] == 18 and x["gender"] == "男", students))
print("18岁男生:", male_18)
# 输出:[{'name':'张三', 'age':18, 'score':85, 'gender':'男'}]
# 示例3:筛选成绩及格(≥60)且年龄<20的学生
qualified_young = list(filter(lambda x: x["score"] >= 60 and x["age"] < 20, students))
print("及格且年龄<20的学生:", qualified_young)
# 输出:[张三、李四、王五、钱七]
# 示例4:筛选姓名包含“张”或“李”的学生(多条件或判断)
name_filter = list(filter(lambda x: "张" in x["name"] or "李" in x["name"], students))
print("姓名含张/李的学生:", name_filter)
# 输出:[张三、李四]
四、实战场景:多条件组合筛选
针对更复杂的筛选需求,可在lambda中组合多个条件(与/或/非),实现精准筛选。
# 场景:处理电商订单数据,筛选符合条件的订单
orders = [
{"order_id": 101, "amount": 89.9, "status": "已支付", "category": "电子产品"},
{"order_id": 102, "amount": 129.9, "status": "已支付", "category": "服装"},
{"order_id": 103, "amount": 159.9, "status": "未支付", "category": "电子产品"},
{"order_id": 104, "amount": 209.9, "status": "已支付", "category": "电子产品"},
{"order_id": 105, "amount": 99.9, "status": "已支付", "category": "食品"}
]
# 需求:筛选“已支付”且“金额>100”且“品类为电子产品”的订单
target_orders = list(filter(
lambda x: x["status"] == "已支付" and x["amount"] > 100 and x["category"] == "电子产品",
orders
))
print("符合条件的订单:", target_orders)
# 输出:[{'order_id':104, 'amount':209.9, 'status':'已支付', 'category':'电子产品'}]
五、注意事项与避坑指南
- filter返回迭代器:Python3中filter返回的是迭代器(节省内存),需用
list()/tuple()转换才能看到具体结果; - lambda判断逻辑要简单:如果筛选规则包含多层嵌套条件、循环、异常处理,建议改用def定义普通函数,避免lambda代码晦涩难懂;
- 处理空值/异常:如果可迭代对象中有
None或缺失字段(如字典少键),需在lambda中增加判断,避免报错:# 处理字典列表中可能缺失的字段 students = [ {"name": "张三", "age": 18}, {"name": "李四"}, # 缺失age字段 {"name": "王五", "age": 20} ] # 筛选age存在且≥18的学生 safe_filter = list(filter(lambda x: x.get("age") and x["age"] >= 18, students)) print(safe_filter) # 输出:[张三、王五] - 替代方案:简单场景下,列表推导式(如
[x for x in nums if x % 2 == 0])与lambda+filter效果一致,且可读性可能更高,可根据习惯选择; - 不要过度使用:如果筛选逻辑需要复用,优先用def定义命名函数,便于调试和维护。