14. 再谈函数的高级用法
14.5 Map函数

引子

除了前面讲解的函数外,还有三个 Python 内置的函数也值得我们仔细学习一下。它们分别是mapreducefilter函数。

这三个函数都提供了一种非常简洁有效的方式,来帮助开发人员操作和转换集合、序列或迭代器中的元素。

下面就让我们来一一探究一下。

map函数的基本概念

什么是map函数?

在回答这个问题之前,我们先想一想是否在实际开发中遇到过如下的需求。

  1. 假设我们有一个以摄氏度表示的温度列表,现在需要将它们转换为华氏度。
  2. 假设我们有一个保存学生信息的字典列表,现在需要提取所有学生的姓名。
  3. 假设我们有两个表示物品价格和数量的列表,现在需要计算每个物品的总成本。

如果遇到过,那么要如何实现这些功能呢?通常的做法:我们可以采用循环的方式遍历每一个数据,然后再执行必要的操作。

这样当然是可行的,但显然不够简洁。

当我们需要在多个值上执行相同的操作时,Python 有一个强大的内置函数可以帮到我们。这个函数就是map函数。

简单来说,map函数就是将给定的函数应用于可迭代对象的每个项,并返回一个新的可迭代对象。

让我们以第一个“将摄氏度转换为华氏度”为例,看一下如何使用map函数。

celsius_temperatures = [25, 30, 18, 12, 40]
fahrenheit_temperatures = list(map(lambda x: (9/5) * x + 32, celsius_temperatures))
print(fahrenheit_temperatures)

输出:

[77.0, 86.0, 64.4, 53.6, 104.0]

在这个例子中,Lambda 函数(lambda x: (9/5) * x + 32)表示的是摄氏度转换为华氏度的公式。我们使用map函数将 Lambda 函数(lambda x: (9/5) * x + 32)应用在celsius_temperatures列表的每个元素上;然后,将转换后的华氏度温度存储在fahrenheit_temperatures列表中。

是不是比使用循环迭代处理更加简洁?

所以,记住:如果我们需要在多个值上执行相同的操作时,map函数往往可以帮助我们写出比使用循环迭代更简洁的代码。

map函数的语法

正如我们在前面看到的,map函数的语法其实很简单:

map(function, iterable)

其中,iterable表示可迭代对象,例如列表、元组、字典等;而function表示我们希望应用在iterable对象中每个元素上的特定函数。

为了更好地理解如何使用map函数,让我们再看一个例子:

def double(x):
    return 2 * x
 
numbers = [1, 2, 3, 4, 5]
 
result = map(double, numbers)

在这个例子中,double函数被定义为返回给定数字的两倍。然后。我们使用map函数将这个double函数应用在numbers列表中的每个元素上。返回结果result将包含转换后的值[2, 4, 6, 8, 10]

map函数的使用

在了解了map函数的语法后,让我们再来看看前面几个例子是如何实现的。

例:假设我们有一个保存学生信息的字典列表,现在需要提取所有学生的姓名。

students = [
    {"name": "Alice", "age": 21},
    {"name": "Bob", "age": 19},
    {"name": "Charlie", "age": 20}
]
 
names = list(map(lambda x: x["name"], students))
print(names)

输出:

['Alice', 'Bob', 'Charlie']

在这里,我们使用map函数将 Lambda 函数(lambda x: x["name"])应用在students列表中的每个字典上,从而提取出"name"属性。最后,提取出来的姓名存储在返回结果names列表中。

例:假设我们有两个表示物品价格和数量的列表,现在需要计算每个物品的总成本。

prices = [10.5, 5.25, 8.75, 12.0]
quantities = [2, 4, 3, 1]
 
total_costs = list(map(lambda p, q: p * q, prices, quantities))
print(total_costs)

输出:

[21.0, 21.0, 26.25, 12.0]

在这个例子中,我们使用map函数将 Lambda 函数(lambda p, q: p * q)以成对的方式应用在pricesquantities这两个列表中的每个元素上。转换后的总成本存储在返回结果total_costs列表中。

map函数的最佳使用实践

如前所述,map函数可以通过一对一映射的方式,帮助我们编写出简洁的代码。为了充分利用map函数,有几个最佳实践我们需要记住:

  1. 尽量使用 Lambda 函数:我们可以利用 Lambda 函数来定义短小而匿名的函数,从而保持代码简洁。例如,我们可以使用 Lambda 函数来重写前面的一个示例:

    numbers = [1, 2, 3, 4, 5]
     
    result = map(lambda x: 2 * x, numbers)
  2. 结合其他函数使用mapmap函数可以与其他内置函数(如filter()reduce())结合使用。这种组合可使我们以最小的工作量执行强大的数据转换。例如:

    numbers = [1, 2, 3, 4, 5]
     
    result = map(lambda x: x ** 2, filter(lambda x: x > 2, numbers))

    在这个例子中,filter函数首先筛选出numbers列表中所有大于2的值;然后,map函数会对这些值进行平方操作,并将结果保存在返回值result中。

    我们暂时可能对filter函数并不了解,没关系,我们会在随后的几节中详细介绍。

总结

总而言之,map函数是 Python 内置的一个强大工具,通过将给定的函数应用在可迭代对象的每个元素上,我们就可以简化数据转换的过程;同时,代码也更加简洁高效。