python:模拟内置函数map的实现
来源:互联网 发布:管家婆软件多少钱 编辑:程序博客网 时间:2024/06/07 05:22
python 的内置函数map
可以对一个迭代器/序列中的每个元素进行操作,然后返回一个被操作后的迭代器对象。
* map
函数默认是c实现的。map
函数非常方便,类似于map
的概念在Java8中也有使用到。以及java中的著名开源框架rxjava
也有大量使用到这个概念。
- 如何在
python
中模拟map
的实现呢?
def mymap(func, *seqs): res = [] # *seqs 相当于拆解成 list1,list2,...,listN for args in zip(*seqs): # zip 之后, args 其实是一个元组 print(args) # *args 相当于拆解成 e1,e2,...,eN ,也就是 func(e1,e2,...,eN) res.append(func(*args)) return res
这段代码实际来自 《learning python》
- 实话说,这段代码不好理解,特别是在没有添加任何注释的情况下。即使你已经知道了python中的参数魔法,你也不见得就能理解
mymap()
这个函数.
这里,我来一句一句剖析这段代码:
首先是第一句
def mymap(func,*seqs):
这句代码表示:调用时肯定要传递至少一个参数进来。对应的是
func
参数。从参数名来看,应该传递一个函数进来。
第二个参数*seqs
是可变参数。传进来后,会被封包成一个元组。
也就是说,假设*seqs
,你传递进来的是1,2,3,4,5
,那么,就会在mymap
中变成(1,2,3,4,5)
这样的一个元组。
当然,事实上,*seqs
对应的应该是多个序列或者多个迭代器,或者两者混合。比如传递进来的是[1,2,3],[4,5,6]
.那么到mymap()
内部就会被封包成([1,2,3],[4,5,6])
这样的一个元组。- 有趣的是,如果混合的话:假设传递进来是
[1,2,3],range(4,7)
,就会被封包成([1,2,3],range(4,7))
- 有趣的是,如果混合的话:假设传递进来是
然后是第二句:
res = []
,这一句不过是定义了一个空的列表。接着是第三句
for args in zip(*seqs):
注意:这一句首先是做了一个
zip
操作。而zip
的参数是*seqs
,这里的*seqs
是对元组的一个拆包。假如上面传递的参数为[1,2,3],[4,5,6]
,那么seqs == ([1,2,3],[4,5,6])
,而在传递给zip
的时候,又加了一个*
操作符。于是进行了拆包操作。也就是,相当于传递给zip
的参数为:[1,2,3],[4,5,6]
。相当于进行zip([1,2,3],[4,5,6])
——这里封了又拆,相当于没有封…
而zip
操作,又会返回一个迭代器,该迭代器其中的每个元素都是一个元组。也就是说,zip([1,2,3],[4,5,6])
之后,得到的迭代器里面的元素分别是(1,4),(2,5),(3,6)
这三个元素。于是这里的args
也分别赋值为这三个元素了。第四句:
print(args)
,这句也不过是打印每个元素罢了。不过通过打印也可以看到,这里的args
确实是一个个元组。第五句:
res.append(func(*args))
这里,外面是一个将元素添加进列表的操作。
里面是进行了一个func
操作。通过这里也可以看出func
必须是一个函数,而不是一个一般的对象。
func
里面的参数,又是一个带*
号的参数。这里的*
号,依然是一个拆包的操作。根据第三句的分析可知,args
是一个元组。在当前场景下,args
分别是:(1,4) , (2,5) , (3,6)
。那么,也就是,调用了3次func
函数。*
操作符,将元组拆包,于是,第一次调用,相当于:func(1,4)
,后面两次类似。
回到最外面的res.append()
。也就是,每次都将func(*args)
的结果收集起来了。第六句:
return res
。这一句就是返回之前收集的所有数据。
通过这简单的6句代码,就模拟了内置函数map
的操作。当然,这段代码,是有优化提升空间的。比如:中间的打印输出是不必要的;也不必要专门弄一个列表去收集数据,可以直接yield
每次结果。这样,得到的就是一个迭代器对象,而不是一个列表。
- 优化如下:
def mymap(func, *seqs): for args in zip(*seqs): yield func(*args)
优化后的代码,更符合内置
map
的行为。
- 这里随便使用一个
mymap()
函数:
def add(*args): return sum(args)rr = mymap(add, [1, 2, 3], range(4, 7))print('rr = ', list(rr))
输出如下:
rr = [5, 7, 9]
ps: 这里的
add
函数,算是对内置sum
函数的一个强化。sum
只能接收可迭代对象。所以,不能进行sum(1,2,3,4,5,6)
这样的操作。而add
函数中,[自动]将*args
封包成一个元组了。也就是说,进行add(1,2,3,4,5,6)
,相当于进行sum((1,2,3,4,5,6))
。这样就可以利用sum
对可变参数之间求和了。~
- ok , 关于对内置函数
map
的模拟就进行到这里了。其实对map
的模拟本身并没有什么意义。因为模拟的map
运行速度必然比不上内置的map
(内置的map
是c实现的)。不过这个模拟,主要是对python 函数参数魔法的一次实践。 - 以上~
彩蛋时刻:
def mymap(func, *seqs): return [func(*args) for args in zip(*seqs)]
def mymap(func, *seqs): return (func(*args) for args in zip(*seqs))
个人以为彩蛋中的实现方式不够友好,可读性降低了。
- python:模拟内置函数map的实现
- python-内置函数map()
- python-内置函数map()
- python 内置函数map、reduce的使用
- Python内置函数-map()函数
- Python 中 map,reduce,和filter 内置函数的方法
- python内置函数:lambda、map、filter
- python内置函数map/reduce/filter
- python内置函数map/reduce/filter
- python map ,reduce filter内置函数使用说明
- python 内置函数map/filter/reduce
- python 内置函数 map、 reduce 、filter
- python 内置函数filter, lambda, map, reduce
- Python 内置函数 lambda、filter、map、reduce
- python内置函数map/reduce/filter
- Python【map、reduce、filter】内置函数使用说明
- python内置函数lambda、filter、map、reduce
- python的内置函数
- 【项目记录】山东大学场馆管理系统之——器材管理
- Python图像处理库(1)
- 【项目记录】山东大学场馆管理系统之——财务管理
- 强题!dft!
- 铺砖问题(状态压缩DP)
- python:模拟内置函数map的实现
- 对比线程安全和可重入函数
- Python图像处理库(2)
- 搜索总结
- 淘淘商城系列——全局异常处理
- 每天学一点Swift----面向对象下(五)
- Java swing 实现angrybird
- PAT (Advanced Level) Practise 1110 Complete Binary Tree (25)
- Sum of Different Primes——素数表+dp