今天模拟定义map函数.写着写着就发现python可变长度参数的机制真是灵活而强大.
假设有一个元组t,包含n个成员:
1
|
t = (arg1,...,argn) |
而一个函数f恰好能接受n个参数:
1
|
f(arg1,...,argn) |
f(t)这种做法显然是错的,那么如何把t的各成员作为独立的参数传给f,以便达到f(arg1,...,argn)的效果?
我一开始想到的是很原始的解法,先把t的各个成员变为字符串的形式,再用英文逗号把它们串联起来,形成一个"标准参数字符串":
1
2
|
str_t = ( str (x) for x in t) str_args = "," .join(str_t) |
str_args成了字符串"arg1,...,argn",这样,
1
|
eval ( '%s(%s)' % (f.__name__,str_args)) |
看起来就相当于:
1
|
f(arg1,...,argn) |
老版本:
1
2
3
4
5
6
7
8
9
10
11
12
|
def imap(func,arr, * arrs): allarrs = (arr,) + arrs args = [] for i in range ( len (arr)): member = [] for ar in allarrs: member.append( str (ar[i])) args.append(member) return ( eval ( '%s(%s)' % (func.__name__, ',' .join(member))) for member in args) print list (imap( float ,( 1 , 2 , 3 , 4 ))) print list (imap(( lambda x,y,z:x + y + z),( 1 , 1 , 1 , 1 ),( 1 , 1 , 1 , 1 ),( 1 , 1 , 1 , 1 ))) |
一运行发现,对于命名函数float可以正常运作,但对于匿名函数lambda就不行了.显然eval思路的局限就在这里.
我突然想起,直接f(*t) 就可以达到目的了!于是,新版本:
1
2
3
4
5
6
|
def imap(func,arr, * arrs): allarrs = (arr,) + arrs return (func( * (ar[i] for ar in allarrs)) for i in range ( len (arr))) print list (imap( float ,( 1 , 2 , 3 , 4 ))) print list (imap(( lambda x,y,z:x + y + z),( 1 , 1 , 1 , 1 ),( 1 , 1 , 1 , 1 ),( 1 , 1 , 1 , 1 ))) |
结果:
1
2
3
|
>>> [ 1.0 , 2.0 , 3.0 , 4.0 ] [ 3 , 3 , 3 , 3 ] |
而且function(*args_tuple)的强大机制在于,args_tuple不一定是元组,任意可迭代对象均可.列表,字典,生成器等.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
>>> def function( * iterable): print iterable >>> function( * ( 1 , 2 , 3 )) ( 1 , 2 , 3 ) >>> function( * [ 1 , 2 , 3 ]) ( 1 , 2 , 3 ) >>> function( * { 1 :' ',2:' '}) ( 1 , 2 ) >>> function( * (i for i in range ( 4 ))) ( 0 , 1 , 2 , 3 ) >>> |
以上这篇对python强大的可变参数传递机制详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://www.cnblogs.com/xiangnan/p/3387342.html