title: 过滤 description: filter() 是 Python 的内置高阶函数,用于过滤序列中的元素。它接收一个函数和一个可迭代对象作为参数,返回一个迭代器(Python 3 中)包含所有使函数返回 True 的元素。

Python filter() 函数详解与实用案例

1. filter() 函数基础

filter() 是 Python 的内置高阶函数,用于过滤序列中的元素。它接收一个函数和一个可迭代对象作为参数,返回一个迭代器(Python 3 中)包含所有使函数返回 True 的元素。

基本语法

filter(function, iterable)

与 map() 的区别

  • map():将函数应用于每个元素,返回处理后的结果
  • filter():根据函数返回值(True/False)决定是否保留元素

2. 基本使用示例

示例1:过滤奇数

def is_odd(n):
    return n % 2 == 1

numbers = [1, 2, 4, 5, 6, 9, 10, 15]
result = list(filter(is_odd, numbers))
print(result)  # 输出: [1, 5, 9, 15]

示例2:过滤空字符串

def not_empty(s):
    return s and s.strip()

data = ['A', '', 'B', None, 'C', ' ']
result = list(filter(not_empty, data))
print(result)  # 输出: ['A', 'B', 'C']

3. 惰性求值特性

filter() 返回的是一个迭代器(Iterator),这意味着它是惰性计算的:

# 不会立即执行计算
filtered = filter(lambda x: x > 5, [3, 6, 2, 8])

# 只有在需要时才会计算
print(next(filtered))  # 输出: 6
print(next(filtered))  # 输出: 8

4. 使用 lambda 表达式简化

filter() 经常与 lambda 表达式结合使用:

# 过滤偶数
numbers = [1, 2, 3, 4, 5, 6]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # 输出: [2, 4, 6]

5. 实用案例:埃拉托斯特尼筛法(素数筛选)

def primes():
    """生成素数序列的生成器"""
    def _odd_iter():
        """生成从3开始的奇数序列"""
        n = 1
        while True:
            n += 2
            yield n
    
    def _not_divisible(n):
        """返回一个判断是否能被n整除的函数"""
        return lambda x: x % n != 0
    
    yield 2  # 第一个素数是2
    it = _odd_iter()  # 初始序列
    while True:
        n = next(it)  # 获取序列的第一个数
        yield n
        it = filter(_not_divisible(n), it)  # 构造新序列

# 打印100以内的素数
print("100以内的素数:")
for prime in primes():
    if prime < 100:
        print(prime, end=' ')
    else:
        break
# 输出: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

6. 现代Python中的替代方案

虽然 filter() 仍然有用,但在许多情况下,列表推导式或生成器表达式可能更清晰:

# 使用filter
result = list(filter(lambda x: x > 5, [3, 6, 2, 8]))

# 等效的列表推导式
result = [x for x in [3, 6, 2, 8] if x > 5]

7. 练习:回文数筛选

def is_palindrome(n):
    """判断一个数是否是回文数"""
    s = str(n)
    return s == s[::-1]

# 测试1-1000的回文数
palindromes = list(filter(is_palindrome, range(1, 1000)))
print("1~1000的回文数:", palindromes)

# 测试验证
test_data = range(1, 200)
expected = [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99, 
            101, 111, 121, 131, 141, 151, 161, 171, 181, 191]
if list(filter(is_palindrome, test_data)) == expected:
    print("测试成功!")
else:
    print("测试失败!")

8. 性能考虑

对于大数据集,filter() 比列表推导式更节省内存,因为它是惰性求值的。但在 Python 3 中,filter() 返回的是迭代器,如果需要多次使用结果,可能需要转换为列表。

9. 总结

  • filter() 是一个强大的函数式编程工具,用于序列过滤
  • 它返回一个迭代器,支持惰性计算
  • 可以与自定义函数或 lambda 表达式结合使用
  • 对于简单过滤,列表推导式可能是更好的选择
  • 在处理大型数据集时,filter() 的内存效率更高

10. 扩展阅读

  • Python 官方文档关于 filter() 的说明
  • 函数式编程概念:map, reduce, filter
  • itertools 模块中的过滤函数(如 filterfalse)
  • 生成器表达式与列表推导式的比较