功能
- map()函数用于对容器中的元素进行映射(或变换)。例如:我 想将列表中的所有元素都乘以2,返回新的列表。
为什么map要设计成一个迭代器的样子呢?
- 节约内存:不再在内存中一次性的生成一个结果列表
语法
map(function,iterable,...)
参数:
- function:是一个提供变换规则的函数,返回变换之后的元素。
- iterator:要映射的可迭代对象,可以是多个序列
可以向 map 函数传递多个 iterable,对应的函数也要接受相同序列数量的参数,如果 iterable 的数量不一样,则取短板,其余的放弃。function 可以使用匿名函数 lambda。
返回值:
- 在python2中返回可迭代对象(列表)
- 在python3中返回可迭代结果(迭代器),如果需要的话,可以用list(…)来强制一个列表
注意:
- 它是一次性的,在遍历过结果一次之后,就用尽了
原理
- 在调用map时,iterable会被遍历,它的元素被逐一传入function()函数中,在function()函数中对元素进行变换
实例
单个可迭代对象
# 单个对象
def add_1(x):
return x + 1
m = map(add_1, [1,2,3,4])
list(m)
# [2, 3, 4, 5]
多个可迭代对象
# 多个对象
def add_num(x, y):
return x + y
m = map(add_num, [1,2,3,4], [1,2,3,4])
list(m)
# [2, 4, 6, 8]
多个序列如果长度不一样,只会处理到最短的元素位置:
# 对象不同长度
def add_num(x, y):
return x + y
m = map(add_num, [1,2,3,4], [1, 2])
list(m)
# [2, 4]
有几个序列,函数就要承接几个参数:
def add_num(x, y, z):
return x + y + z
l1 = [1, 2, 3]
[*map(add_num, l1, l1, l1)]
[3, 6, 9]
使用匿名函数
# 匿名函数
m = map(lambda x,y: x+y, [1,2,3,4], [1, 2])
list(m)
# [2, 4]
其他
对于函数的输入已经是参数元组的情况,可以 使用 itertools.starmap() 操作。它创建一个迭代器,使用从可迭代对象中获取的参数来计算该函数。当参数对应的形参已从一个单独可迭代对象组合为元组时(数据已被“预组对”)可用此函数代替 map()。map() 与 starmap() 之间的区别可以类比 function(a,b) 与 function(*c) 的区别。
import itertools
t = [(2,5), (3,4)]
# 元组内操作(相乘)
sm = itertools.starmap(lambda x,y: x*y, t)
list(sm)
# [10, 12]
列表表达式
map 的功能可以用列表表达式来代替:
l = [-2, -1, 0]
[abs(x) for x in l]
# [2, 1, 0]
[x**2 for x in l]
# [4, 1, 0]
l_1 = [1, 2, 3]
l_2 = [10, 20, 30]
[x * y for x, y in zip(l_1, l_2)]
# [10, 40, 90]
在大多数情况下,与 map 相比,使用列表生成器式更简洁明了,但也有人认为 map 作为高阶函数,能更加突出函数,弱化了循环的表达,让处理逻辑看起来更加明显。
NumPy 代替
在数据科学中,不需要按 map 模式的计算,两个序列之间的操作被认为是一个矩阵计算,NumPy 可以非常好地完成这些,比 map() 和列表表示更为明确。
import numpy as np
a = np.array([-2, -1, 0])
print(np.abs(a))
# [2 1 0]
print(a**2)
# [4 1 0]
a_1 = np.array([1, 2, 3])
a_2 = np.array([10, 20, 30])
print(a_1 * a_2)
# [10 40 90]