Python starmap()和map()应用于数据,Python内置的map()
函数是高阶函数,能对可迭代对象中的每个元素进行映射。简易版的map()
函数如下所示:
map = (lambda function, arg_iter:
(function(a) for a in arg_iter)
)
若arg_iter
为可迭代对象,以上定义完全正确,但实际的map()
函数比这里的实现更复杂,能处理多个可迭代对象。
itertools
模块的starmap()
函数实际上是map()
函数的*a
版本,如下定义:
starmap = (lambda function, arg_iter:
(function(*a) for a in arg_iter)
)
相比于map()
函数,该实现方法在语义上有微小的变化,使之更适于处理嵌套元组式的数据结构。
map()
函数也可以接收多个可迭代对象作为输入参数,这些可迭代对象被zip
在一起,行为类似于startmap()
。由源可迭代对象组成的各个元素构成了给定函数的输入参数。
可以通过下面两种表达式定义map(function, iter1, iter2, ..., itern)
:
map1 = (lambda function, *iters:
(function(*args) for args in zip(*iters))
)
map2 = (lambda function, *iters:
(starmap(function, zip(*iters)))
)
不同迭代器中的值通过zip(*iters)
组成参数元组,然后通过*args
结构体展开为给定函数的参数列表,所以可以基于更抽象的starmap()
函数构建出map()
函数。
理解了上面的计算过程,就可以基于startmap()
函数重新定义旅行数据的计算过程了。在创建Leg
对象之前,首先创建位置点对,每个数据对如下所示:
((Point(latitude=37.54901619777347, longitude=-76.33029518659048),
Point(latitude=37.840832, longitude=-76.273834)),
...,
(Point(latitude=38.330166, longitude=-76.458504),
Point(latitude=38.976334, longitude=-76.473503))
)
接着通过starmap()
函数组合生成Leg
对象,如下所示:
from Chapter_7.ch07_ex1 import float_lat_lon, Leg, Point
from Chapter_6.ch06_ex3 import row_iter_kml
from Chapter_4.ch04_ex1 import legs, haversine
from typing import List, Callable
make_leg = (lambda start, end:
Leg(start, end, haversine(start,end))
) # type: Callable[[Point, Point], Leg]
with urllib.request.urlopen(url) as source:
path_iter = float_lat_lon(row_iter_kml(source))
pair_iter = legs(path_iter)
trip = list(starmap(make_leg, pair_iter))
make_leg()
函数的输入是一对Point
对象,返回值是包含起点、终点和距离的Leg
对象。第4章中定义的legs()
函数生成了包含一段路径起点和终点的Point
对象二元组,用作make_leg()
的输入,并最终生成Leg
对象。
使用starmap(function, some_list)
方法避免了写出(function(*args) for args in some_list)
这样冗长的生成器表达式,也更易读。