在Python内置的高阶函数中,filter()专门用于批量筛选可迭代对象中的元素。与map()负责批量加工不同,filter()只做筛选,不修改元素,两者互补。掌握filter()能大幅简化数据去空、异常值过滤、条件提取等场景的代码,结合lambda匿名函数一行即可完成。
- filter(function, iterable)
复制代码
function是必填的判断函数,返回值必须是布尔值True或False,只写函数名不加括号。iterable可以是列表、元组、字符串、集合、生成器等。返回值在Python3中是一个filter迭代器对象,而非列表。
另一种特殊用法是传递None作为function:
此时filter自动过滤掉所有Python假值,包括0、0.0、空字符串、空列表、空字典、None、False。
基础实战案例一:筛选列表中的偶数
定义判断函数:
- def is_even(x):
- return x % 2 == 0
复制代码
准备数据并调用filter:
- num_list = [1, 2, 3, 4, 5, 6, 7, 8]
- filter_obj = filter(is_even, num_list)
- result = list(filter_obj)
- print(result) # [2, 4, 6, 8]
复制代码
核心原理:is_even只负责判定单个元素是否符合条件,返回True/False。filter自动遍历数据源,逐个调用判断函数,True保留,False丢弃,最终返回迭代器。
实战案例二:结合lambda一行过滤
- num_list = [2, 6, 1, 9, 4, 7]
- res1 = list(filter(lambda x: x > 5, num_list))
- print(res1) # [6, 9, 7]
- str_list = ["py", "java", "go", "rust", "c"]
- res2 = list(filter(lambda s: len(s) > 3, str_list))
- print(res2) # ['java', 'rust']
复制代码
实战案例三:结合内置函数做数据校验
- mix_list = [123, "python", None, "java", 3.14, ""]
- str_res = list(filter(lambda x: isinstance(x, str), mix_list))
- print(str_res) # ['python', 'java', '']
- raw_data = ["admin", "", "root", None, "guest", " "]
- valid_data = list(filter(lambda s: s and s.strip(), raw_data))
- print(valid_data) # ['admin', 'root', 'guest']
复制代码
实战案例四:多条件筛选结构化数据(字典列表)
- user_list = [
- {"name": "张三", "age": 18, "is_vip": True},
- {"name": "李四", "age": 16, "is_vip": False},
- {"name": "王五", "age": 22, "is_vip": True},
- {"name": "赵六", "age": 17, "is_vip": True}
- ]
- vip_adult = list(filter(lambda u: u["age"] >= 18 and u["is_vip"], user_list))
- print(vip_adult)
- # [{'name': '张三', 'age': 18, 'is_vip': True}, {'name': '王五', 'age': 22, 'is_vip': True}]
复制代码
六大致命踩坑点(新手必读)
1. Python3中filter返回的是迭代器,不是列表,不能直接打印或下标取值。必须手动转换,如list(filter_obj)。注意转换后迭代器耗尽,再次转换会得到空列表。
- f_obj = filter(lambda x: x > 0, [-1, 2, -3, 4])
- print(list(f_obj)) # [2, 4]
- print(list(f_obj)) # [] 第二次已耗尽
复制代码
2. filter采用惰性求值,调用时只记录规则和数据源,不立即计算。只有list()转换或for遍历时才逐个校验,适合处理大数据量,内存占用低。
3. 传入的判断函数中不要写print、赋值等无关逻辑,filter只关心返回值True/False,多余操作既无效又可能影响性能。
4. 迭代器单向一次性,遍历后元素耗尽。若需多次使用,应提前转为列表保存。
5. filter(None)只过滤内置假值,不会递归过滤嵌套空容器。例如[[], 1, [2,3]]中空列表[]是假值会过滤,但内部空元素不会。
6. 可迭代对象不限列表,字符串、元组等皆可过滤。
- s = "pythonabc"
- vowel = list(filter(lambda c: c in {"a","e","i","o","u"}, s))
- print(vowel) # ['o', 'a']
- t = (-5, 3, -2, 7)
- neg = list(filter(lambda x: x < 0, t))
- print(neg) # [-5, -2]
复制代码
filter vs 列表推导式 vs for循环 选型建议
传统for循环适合超复杂多分支业务逻辑,代码冗余但灵活。列表推导式简洁直观,但立即求值,大数据量时内存占用高。filter+lambda惰性求值、省内存,条件可复用于函数式编程。
简单筛选追求直观用列表推导式;大数据量、流式处理或条件复用选filter;多层嵌套复杂业务用for循环。
三大高阶函数分工:map()无差别加工所有元素(改值不改数量);filter()按条件筛选保留元素(不改值只改数量);reduce()逐个聚合返回单个值(求和求积等)。组合使用可写出优雅高效的函数式数据管道。
掌握filter()与map(),已迈入Python函数式编程大门。后续可结合reduce()实现更强大的数据处理流水线。 |