Python的map函数理解四式

​前言

某人在学习Python函数的时候, 介绍map()函数的使用:

defsqr(x):

returnx **2

a = [1,2,3]

printmap(sqr, a)

Python的map函数理解四式_第1张图片


这个map函数是python的内嵌的函数, 那么如何手写一个自己的map函数,实现内嵌map函数一模一样的功能呢?

第一式: 不固定参数

Python内嵌的map函数允许不固定参数, 如下图所示, map第一个参数是一个函数, 剩余的不固定参数只要iterative类型就可以。 譬如,下面可以是元组和数组。

defadd(x, y):

returnx + y

a = (2,3,4)

b = [10,5,3]

printmap(add, a, b)

Python的map函数理解四式_第2张图片


那么如何实现这个不固定参数的读取呢?Python给了*var的形式,可以接受任意参数。 某人根据map的功能进行设计, 先将之后的参数按行拼接成参数, 然后调用函数,得到返回值。

Python的map函数理解四式_第3张图片


于是,某人实现了如下函数:

defmy_map(func, *lst):

res = []

m =len(lst)

n =len(lst[0])

foriinrange(n):

args = []

forjinrange(m):

args.append(lst[j][i])

res.append(func(*args))

returnres

跑一下, 杠杠的!和map()结果一致。

Python的map函数理解四式_第4张图片


但是, 这个是不是内嵌map的全部实现呢?

第二式: 对齐Iterator,返回默认值

所谓天大差别, 不过一横, 就算差了一点, 任然差别太大。 所以在比较my_map和内嵌的map的时候,是不是还要边界检查。  前面测试了相同长度的数组的map, 对于不同长度的数组的map呢?

a = (2,3,4)

b = [10,5,3]

printmap(lambdax,y:'{}~{}'.format(x,y), a,b+[0])

printmy_map(lambdax,y:'{}~{}'.format(x,y),  a,b+[0])

Python的map函数理解四式_第5张图片


可以上面结构看到, 内嵌的map会按最大长度自动补齐。

那么一种实现,就是找到数据里面最长的, 将所有不够长的补齐None值,之后再调用my_map()

Python的map函数理解四式_第6张图片


另外一种,我就是利用iterator到结束之后, 默认返回None值。默认的next()函数的第二个参数,可以是返回的默认值。

defmy_map2(func, *lst):

res = []

its = [iter(it)foritinlst]

ln =max([len(it)foritinlst])

whileln >0:

args = [next(it,None)foritinits]

res.append(func(*args))

ln -=1

returnres

a = (2,3,4)

b = [10,5,3]

printmap(lambdax,y:'{}~{}'.format(x,y), a, b+[0])

printmy_map2(lambdax,y:'{}~{}'.format(x,y),  a, b+[0])

Python的map函数理解四式_第7张图片


效果不错,那么是不是就搞定了呢?

第三式: Python 2,3兼容,内部类型变换

是不是上面实现的my_map2(),就是一个python2和python3下都和map函数一致呢? 前面,我们在使用print函数的时候, 没有使用括号, 那么明显是在Python2的环境下面, 那么对于Python3环境下呢?在Python3下测试一下吧:

Python的map函数理解四式_第8张图片


我们发现打印了是一个map object。嘿, 内嵌map函数的实现, 在Python2和Python3中似乎很不一样。 如果我们试图通过subscribe[]来访问的的时候,发现这个map并不可以通过index来访问。

Python的map函数理解四式_第9张图片


那么基本判断就是一个iterative的对象。 但是如何打印具体内容出来看呢? 最好是通过Python的内部变量之间转换进行list()

Python的map函数理解四式_第10张图片


这样, 那么我们再次调用非对齐的map来测试:

print(list(map(lambdax,y:'{}~{}'.format(x,y), a, b+[0])))



我们发现在Python3里面不再按照最长的iteration来进行对齐了, 而是按照最短的来对齐。因此, 我们可以把最长换成最短来模拟Python3中的map。

defmy_map3(func, *lst):

res = []

its = [iter(it)foritinlst]

ln =min([len(it)foritinlst])

whileln >0:

args = [next(it,None)foritinits]

res.append(func(*args))

ln -=1

returnres

是不是my_map3()在Python3中,就是最好的模拟呢?

第四式: 对齐Iterator,返回默认值

但是毕竟Python3中返回的是一个iterator,一个差异就是, 我们返回一个数组(数组可以通过subscribe[]访问), 我们知道iterator本身,可以通过generator来进行简化,并且这种lazy实现, 会提高调用效率。 这时候伟大的yield关键词上场了。

一般来说,在Python中, 如何用好yield关键词和decorator功能,都会极大提高工作效率的,也是反应一个人Python功底的东东。

defmy_map4(func, *lst):

its = [iter(it)foritinlst]

ln =min([len(it)foritinlst])

whileln >0:

args = [next(it,None)foritinits]

yieldfunc(*args)

ln -=1

至此 ,我们可以打印出来,看my_map4返回的也是一个iterative object,这个generator object和map object有着异曲同工之妙。  另外再通过list进行内部变量转化,看到它实现的功能也一致。

Python的map函数理解四式_第11张图片


至此, 某人听完第三式和第四式的实现, 对Python大大失去兴趣,坑太多! ! !

小结:

本人设计的一个面试题,并且自我回答,通过对Python2和Python3中map函数的测试, 试图自己实现这个内嵌函数, 经验有限,希望大家对map有更为深入的了解,尤其Python2和Python3中实现的巨大差异。  抛砖引玉,也希望看到大家的深刻反馈!以便我进一步更新认知。

Python的map函数理解四式_第12张图片


Python的map函数理解四式_第13张图片

你可能感兴趣的:(Python的map函数理解四式)