如何使用Python过滤器功能

来自菜鸟教程
跳转至:导航、​搜索

介绍

Python 内置的 filter() 函数可用于从现有的可迭代对象(如 listdictionary)创建新的迭代器,使用我们提供的一个功能。 iterable 是一个可以“迭代”的 Python 对象,也就是说,它将按顺序返回项目,以便我们可以在 for 循环中使用它。

filter() 函数的基本语法是:

filter(function, iterable)

这将返回一个过滤器对象,它是一个可迭代的。 我们可以使用 list() 之类的函数来列出过滤器对象中返回的所有项目。

filter() 函数提供了一种过滤值的方法,通常比 列表理解 更有效,尤其是当我们开始处理更大的数据集时。 例如,列表推导将创建一个新列表,这将增加该处理的运行时间。 这意味着在我们的列表推导完成其表达式后,我们将在内存中拥有两个列表。 但是,filter() 将创建一个简单的对象,其中包含对原始列表的引用、提供的函数以及原始列表中的位置索引,这将占用更少的内存。

在本教程中,我们将回顾使用 filter() 的四种不同方式:使用两种不同的可迭代结构,使用 lambda 函数,以及没有定义函数。

filter() 与函数一起使用

filter() 的第一个参数是 函数,我们用它来决定是包含还是过滤掉每个项目。 对于作为第二个参数传递的迭代中的每个项目,该函数都会调用一次,并且每次返回 False 时,都会删除该值。 由于这个参数是一个函数,我们可以传递一个普通函数,也可以使用 lambda 函数,特别是当表达式不太复杂时。

以下是带有 filter()lambda 的语法:

filter(lambda item: item[] expression, iterable)

使用如下所示的列表,我们可以将 lambda 函数与我们想要评估列表中每个项目的表达式合并:

creature_names = ['Sammy', 'Ashley', 'Jo', 'Olly', 'Jackie', 'Charlie']

要过滤此列表以查找以元音开头的水族馆生物的名称,我们可以运行以下 lambda 函数:

print(list(filter(lambda x: x[0].lower() in 'aeiou', creature_names)))

在这里,我们将列表中的一个项目声明为 x。 然后我们将表达式设置为访问每个字符串的第一个字符(或字符“零”),因此 x[0]。 降低每个名称的大小写确保这将匹配我们表达式中的字符串 'aeiou' 中的字母。

最后我们传递了可迭代的 creature_names。 与上一节一样,我们将 list() 应用于结果,以便从迭代器 filter() 返回创建一个列表。

输出将如下:

Output['Ashley', 'Olly']

使用我们定义的函数可以实现相同的结果:

creature_names = ['Sammy', 'Ashley', 'Jo', 'Olly', 'Jackie', 'Charlie']

def names_vowels(x):
  return x[0].lower() in 'aeiou'

filtered_names = filter(names_vowels, creature_names)

print(list(filtered_names))

我们的函数 names_vowels 定义了我们将实现过滤 creature_names 的表达式。

同样,输出如下:

Output['Ashley', 'Olly']

总的来说,lambda 函数使用 filter() 获得的结果与我们使用常规函数时相同。 随着用于过滤数据的表达式的复杂性增加,定义正则函数的必要性也在增加,这可能会提高我们代码的可读性。

Nonefilter() 一起使用

我们可以将 None 作为第一个参数传递给 filter() 以让返回的迭代器过滤掉 Python 认为“虚假”的任何值。 通常,Python 将长度为 0 的任何内容(例如空列表或空字符串)或数值上等同于 0 的任何内容都视为假,因此使用了“假”一词。

在以下情况下,我们希望过滤列表以仅显示水族箱中的水族箱编号:

aquarium_tanks = [11, False, 18, 21, "", 12, 34, 0, [], {}]

在这段代码中,我们有一个包含 整数 、空序列和 布尔值 的列表。

filtered_tanks = filter(None, aquarium_tanks)

我们将 filter() 函数与 None 一起使用,并将 aquarium_tanks 列表作为我们的迭代传递。 由于我们已将 None 作为第一个参数传递,因此我们将检查列表中的项目是否被认为是错误的。

print(list(filtered_tanks))

然后我们将 filtered_tanks 包装在 list() 函数中,以便在打印时返回 filtered_tanks 的列表。

这里的输出只显示整数。 所有评估为 False 的项目,其长度等于 0,被 filter() 删除:

Output[11, 25, 18, 21, 12, 34]

注意:如果我们不使用 list() 并打印 filtered_tanks,我们将收到类似这样的过滤器对象:<filter object at 0x7fafd5903240>。 过滤器对象是一个可迭代对象,因此我们可以使用 for how-to-construct-for-loops-in-python-3 循环它,或者我们可以使用 list() 将它变成一个列表,我们在这里这样做是因为它是一个很好的方法审查结果。


对于 None,我们使用 filter() 快速从列表中删除被认为是错误的项目。

filter() 与字典列表一起使用

当我们有更复杂的数据结构时,我们仍然可以使用 filter() 来评估每个项目。 例如,如果我们有一个字典列表,我们不仅要遍历列表中的每个项目(其中一个字典),而且我们可能还想遍历字典中的每个键:值对以评估所有的数据。

例如,假设我们有一个水族馆中每个生物的列表以及每个生物的不同细节:

aquarium_creatures = [
  {"name": "sammy", "species": "shark", "tank number": "11", "type": "fish"},
  {"name": "ashley", "species": "crab", "tank number": "25", "type": "shellfish"},
  {"name": "jo", "species": "guppy", "tank number": "18", "type": "fish"},
  {"name": "jackie", "species": "lobster", "tank number": "21", "type": "shellfish"},
  {"name": "charlie", "species": "clownfish", "tank number": "12", "type": "fish"},
  {"name": "olly", "species": "green turtle", "tank number": "34", "type": "turtle"}
]

我们想通过我们提供给函数的搜索字符串来过滤这些数据。 为了让 filter() 访问每个字典和字典中的每个项目,我们构造了一个嵌套函数,如下所示:

def filter_set(aquarium_creatures, search_string):
    def iterator_func(x):
        for v in x.values():
            if search_string in v:
                return True
        return False
    return filter(iterator_func, aquarium_creatures)

我们定义了一个 filter_set() 函数,它以 aquarium_creaturessearch_string 作为参数。 在 filter_set() 中,我们将 iterator_func() 作为函数传递给 filter()filter_set() 函数将返回由 filter() 生成的迭代器。

iterator_func()x 作为参数,它表示我们列表中的一个项目(即单个字典)。

接下来 for 循环访问我们字典中每个 key:value 对中的值,然后使用条件语句检查 search_string 是否在 v 中,表示一个值。

与我们之前的示例一样,如果表达式的计算结果为 True,则该函数将该项添加到过滤器对象中。 这将在 filter_set() 函数完成后返回。 我们将 return False 定位在循环之外,以便它检查每个字典中的每个项目,而不是在单独检查第一个字典后返回。

我们调用 filter_set() 与我们的字典列表和我们想要找到匹配的搜索字符串:

filtered_records = filter_set(aquarium_creatures, "2")    

函数完成后,我们将过滤器对象存储在 filtered_records 变量中,我们将其转换为列表并打印:

print(list(filtered_records))      

我们将从该程序中收到以下输出:

Output[{'name': 'ashley', 'species': 'crab', 'tank number': '25', 'type': 'shellfish'}, {'name': 'jackie', 'species': 'lobster', 'tank number': '21', 'type': 'shellfish'}, {'name': 'charlie', 'species': 'clownfish', 'tank number': '12', 'type': 'fish'}]

我们使用搜索字符串 2 过滤了字典列表。 我们可以看到已经返回了包含带有 2 的坦克编号的三个字典。 使用我们自己的嵌套函数,我们可以访问每个项目并根据搜索字符串有效地检查每个项目。

结论

在本教程中,我们学习了在 Python 中使用 filter() 函数的不同方法。 现在,您可以将 filter() 与您自己的函数、lambda 函数或 None 一起使用来过滤具有不同数据结构复杂性的项目。

尽管在本教程中,我们立即以列表格式打印了 filter() 的结果,但在我们的程序中,我们可能会使用返回的 filter() 对象并进一步操作数据。

如果您想了解更多 Python,请查看我们的 How To Code in Python 3 系列和我们的 Python 主题页面