跳至内容
Python

Python filter(): 保留所需内容

了解如何使用 Python 的 filter() 函数从列表或其他可迭代对象中提取项。理解 filter 与类似 Python 工具的关键差异。
Josef Waples's photo
Josef Waples
已更新 · 7分钟 阅读

使用 AI 探索

ChatGPTClaudePerplexity

创建您的免费账户

实践并学习路径你的进步。

使用 Google 继续
继续操作即表示您接受我们的《使用条款》和《隐私政策》,并同意您的数据存储在美国。

筛选是 Python 中最常见的任务之一,因此 Python 提供了便捷的做法。最简单的筛选方式之一就是使用内置的 filter() 函数。顾名思义,filter() 让您只取出满足某个条件(或多个条件)的项。

本指南将带您了解它的工作原理、适用场景,以及它与其他筛选工具的对比。请继续阅读!

Python filter() 的作用

filter() 可让您从列表、元组或任意可迭代对象中取出元素,但前提是这些元素能通过您的测试。您提供一个函数(有时称为谓词),它接收每个项并返回 True 或 False。如果测试通过(即您的函数返回 True),filter() 就会保留该项;否则会跳过。这已经相当直观,我们继续。

Python filter() 语法

格式如下:

filter(function, iterable)
  • function:指定要对每个项应用的测试。它应接收一个参数并返回 True 或 False。

  • iterable:提供列表、元组、字符串,或任何可被循环遍历的对象。

调用 filter() 时,它会返回一个特殊的 filter 对象,而不是直接返回列表或元组。要实际使用筛选结果,通常需要把输出包裹为列表或元组。这样的设计让 filter() 更高效,但在编写代码时需要牢记这一点。

Python filter() 示例

我们来实际练习一下。

结合自定义函数的 Python filter()

让我们把 filter() 和自己编写的函数配合使用。

假设您只想保留列表中的偶数:

def is_even(num):
    return num % 2 == 0

numbers = [1, 2, 3, 4, 5, 6]
result = filter(is_even, numbers)
print(list(result))

这将打印:

[2, 4, 6]

请注意,is_even 会检查一个数字能否被 2 整除。filter() 使用我们的自定义函数测试每个项,并保留那些通过测试的项。

结合 lambda 函数的 Python filter()

当然,并非每次筛选都需要完整的函数定义。有时,您的筛选规则非常简单或只在一个位置使用,定义具名函数就显得多此一举。

下面是相同的偶数示例,但使用 lambda 来进行简洁的就地测试:

numbers = [1, 2, 3, 4, 5, 6] 
result = filter(lambda x: x % 2 == 0, numbers) 
print(list(result))

您将得到与前面相同的输出。

当您希望代码简洁聚焦时,结合 filter() 使用 lambda 尤为常见。它非常适合一次性的筛选任务,让您在需要的地方直接表达规则。

在函数位置使用 None 的 Python filter()

有时,您想用 filter() 去除空值或假值,例如 0、空字符串、None 或 False,并且希望不用编写自定义函数。

Python 有个妙招:如果将 filter() 的函数参数设为 None,filter() 会自动移除所有被 Python 视为 False 的项。

示例如下:

items = [0, 1, '', 'hello', [], [2, 3], None, False, True] 
result = filter(None, items) 
print(list(result))

这将打印:

[1, 'hello', [2, 3], True]

筛选文本数据

现在让我们把 filter() 用在一个实用的日常问题上。假设您有一个单词列表,只想要那些以字母 'a' 开头的单词。在处理文本时,这种有针对性的筛选经常会遇到。

words = ['apple', 'banana', 'apricot', 'cherry', 'avocado'] 
result = filter(lambda word: word.startswith('a'), words) 
print(list(result))

您将得到:

['apple', 'apricot', 'avocado']

结合多个条件进行筛选

有时,您的筛选标准会更复杂。如果需要满足多个条件怎么办?以下是使用 lambda 的实现。在这个示例中,我们寻找既是偶数又大于 10 的数字。

numbers = [4, 10, 12, 15, 20, 23, 28] 
result = filter(lambda x: x % 2 == 0 and x > 10, numbers) 
print(list(result))

这将打印:

[12, 20, 28]

(如果条件更多,我会考虑从 lambda 切换为具名函数以提高清晰度。)

filter() 与列表推导式

列表推导式是另一种常用的选择方式。两种方法都能筛选数据,但各有风格。

下面再次给出偶数示例,这次使用列表推导式:

numbers = [1, 2, 3, 4, 5, 6] 
result = [x for x in numbers if x % 2 == 0] 
print(result)
[2, 4, 6]

filter() 和列表推导式都能完成任务。对于直观的简单筛选,列表推导式通常更易读。

另一方面,当您已经在使用函数式风格,或想把多个处理步骤串联起来时,filter() 会很合适。

更高级的用法

我们来找一些更有意思的场景:

与其他可迭代对象配合的 filter()

与对列表的用法相同,filter() 也适用于任意可迭代对象,比如元组、集合,甚至 生成器表达式。这很重要,因为您的数据并不总是以列表形式存在。

以下演示如何筛选一个元组:

numbers = (10, 15, 20, 25, 30) 
result = filter(lambda x: x > 20, numbers) 
print(tuple(result))

这将打印:

(25, 30)

请记得在需要直接使用结果时,将 filter 对象转换为您想要的类型(列表、元组等)。

另外我也提到了生成器,为了完整起见,再展示一个结合生成器进行筛选的示例:

numbers = (x for x in range(10))
result = filter(lambda x: x % 2 == 0, numbers)
print(list(result))

这是一个生成器,因为这行代码:numbers = (x for x in range(10)) 创建了一个生成器对象。(它是惰性的,不会一次性生成所有值。)

最后一行:print(list(result)) 通过将惰性的 filter 对象转换为列表来强制求值。

将 filter() 与 map() 结合

如果您既想筛选又想变换数据,比如我们接下来的示例,只对列表中的偶数求平方,该怎么办?

Python 允许将 filter() 与 map() 组合使用。首先,filter() 选出您想要的项,然后 map() 对每个项再应用一个函数。

实践如下:

numbers = [1, 2, 3, 4, 5, 6] 
evens = filter(lambda x: x % 2 == 0, numbers) 
squared = map(lambda x: x ** 2, evens) 
print(list(squared))

这将打印:

[4, 16, 36]

通过将 filter() 和 map() 串联,您可以构建清晰、可读的数据管道:先选出关心的项,再按需进行变换。在您的工作中会有机会用到这种模式。

注意事项

尽管 filter() 很方便,但也有一些常见误区:

  • filter() 返回的是一个 filter 对象,而不是列表。这可能会在您期待立即看到结果时出错。如果需要查看或复用结果,请将其包裹为列表(或元组)。

  • filter() 一次只处理一个可迭代对象。如果您想基于多个列表进行筛选,需要先将它们 zip 在一起,或采用其他方法。

  • filter() 是惰性的。它不会真正处理数据,直到您将其转换为列表、元组,或对其进行循环。在调试时请牢记这一行为。

结语

如您所见,Python 的 filter() 函数为您提供了一种快速清理数据的方法,只保留重要内容。无论是编写一次性的 lambda,还是传入具名函数,filter() 都能帮上忙。

如果您还不清楚如何使用 filter(),或者觉得这个内容比较简单并想继续学习,我们有很好的资源可供参考。我推荐我们的 Python Programming Fundamentals 技能路径。 


Josef Waples's photo
Author
Josef Waples

我是数据科学编辑,曾为科学期刊发表的研究论文撰稿。我的兴趣领域包括线性代数、统计学、R 等相关主题。

Python Filter 常见问答

Python 的 filter() 函数有什么作用?

filter() 函数接收一个函数和一个可迭代对象,并返回一个仅包含通过测试项的新可迭代对象。测试函数应对需要保留的项返回 True,对需要跳过的项返回 False。

为什么需要用 list() 或 tuple() 包裹 filter() 的结果?

filter() 返回一个 filter 对象,它是一个迭代器。要查看或复用筛选结果,通常需要使用 list() 或 tuple() 将其转换为列表或元组。这一步对打印、调试或将结果传递给其他函数至关重要。

不写自定义函数也能用 filter() 吗?

可以。您可以使用 lambda 函数来进行简短的一次性测试,或者将函数参数传入 None,以自动移除所有“假值”,如 0、''、None 和 False。

filter() 与列表推导式相比如何?

filter() 和列表推导式都能筛选数据,但对于简单条件,列表推导式通常更易读。当需要通过函数复用逻辑,或与 map() 等工具串联时,filter() 很有用。

能在 filter() 中应用多个条件吗?

当然可以。您可以在测试函数或 lambda 中使用逻辑运算符组合多个条件。对于复杂逻辑,通常使用具名函数更有利于可读性。

主题
Python

通过 DataCamp 学习 Python

课程

Python 入门

4 小时
7.1M
只需 4 小时就能掌握 Python 数据分析基础知识。 本在线课程将介绍 Python 接口并探索常用包。
查看详情开始课程

创建您的免费账户

实践并学习路径你的进步。

使用 Google 继续
继续操作即表示您接受我们的《使用条款》和《隐私政策》,并同意您的数据存储在美国。
查看更多