今天模拟定义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