apply、map及函数工具、list的再构造
时间:2010-06-12 来源:hkebao
apply、map及函数工具、list的再构造
时间:2010-6-12
在python中,有两种方式可以用来定义一个函数。用def可以定义有名字的函数。用lambda可以定义匿名函数。由于在实际调用一个函数时,实参的个数可能是一个也可能是两个,还可能是多个。因此在形参前面加上*或**来处理这个情况。
笔记:哦明白了*与** 经常会在类中看到原来是定义可变长的参数列表的!
示例:
>>> def test(*x):
... if len(x) > 0:
... for c in x:
... print c
... else:print None
这样就可以定义可变长度的一个参数列表了。就可以如下调用它!
test();也可以使用一个实参的形式调用,比如:test(4);还可以以多个实参的形式调用,比如:test(1,2,3,4)。
但不管是哪种方式,在调用的时候实际参数的个数都已经确定下来了,一个就是一个,两个就是两个。现在假设在一个程序中有一 个list,比如叫userInput,这个list中的成员是由用户在使用程序时交互确定的,在运行中可能有一个成员,也可能有多个成员,这一切都要看 用户怎么操作。现在要用test函数把userInput打出来。
笔记:当要传入一个序列的时候可能就会出现个数不确定的情况了。要打印的话也是整个序列了。怎么办呢?
在python中还有更简单的办法,就是使用内置函数apply:
- apply(test, userInput)
表示把userInput作为test的参数,也就是说比如在程序运行时,userInput得到的值是[1,2,3],那么就相当于test(1,2,3)。如果userInput得到的实际值是[1,2],那么就相当于test(1,2)。
>>> userinput=[1,2,3]
>>> apply(test,userinput)
1
2
3
笔记:还记得上次那个JS培训不?里面讲到一个arguments对象了吧。感觉这个与那是一个道理的。因为用户的实参个数是不固定的。所以我们可以使用这个关键字进行处理!
总之,定义函数时在形式参数面前加上*或**是为了,在调用这个函数的时候可以灵活地提供实参的个数。而apply则是为了可以用不定个数的实际参数来调用函数。
笔记:我们在处理这种可变长参数的时候就非常有效了!
更进一步:
其实还可以更简单,连apply都不用,直接写成:
- test(*userInput)
这表示的意思就是apply(test,userInput)
>>> test(*userinput)
1
2
3
笔记:我感觉这样处理的话将实参与形参捆绑处理了。
可以把函数定义的中形参前面的*理解为“打包”操作,也就是把多余的实参都打包在一个tuple中;可以把调用时的*理解 为“解包”的操作,比如说这里表示:调用test函数,实参是对userInput“解包”后所得的东西。当然对于**也可以以相同的方式理解。在 test(**D)的形式中,D必须为一个dictionrary,相当于test(key1=value1,key2=value2...)。
笔记:
明白了!!!!
* 表示的是tuple
** 表示的是字典
函数形参如果这样写* 就表示这个参数接收可变长的tuple参数
如果形参这样写** 就表示接收可变长的字典类型的参数!
介绍一下map函数
map(function, seq1,seq2...)
map实际上是python中一大类函数的一个代表,这类函数可以被称为函数工具。常用的函数中,同类的还有filter和reduce。
- filter(func or None,seq)
它返回一个序列类型的值。表示把seq中的每个成员依次代入function中,如果为真则它将成为返回序列中的一个成员。
再来看reduce函数:
- reduce(function, sequence[, initial])
表示把sequence按照function提供的规则进行计算,最后算出一个值来。这个function必须具有两个参数,
>>> L = [1,2,3,4,5]
>>> reduce((lambda x,y: x*y),L)
120
含义:相当把L里面的数据作一次运算处理。这个运算是一个
从上面介绍可以看出,map、filter或者reduce实际都是对序列类型数据的成员进行操作。由于这种操作在python是非常普遍的,因此在python 2.0后提供了一种叫"list的再构造"的语法形式来进行类似的操作。
示例:
>>> L = [1,2,3,4,5]
>>> map((lambda x:x**2),L)
[1, 4, 9, 16, 25]
理解:map的工具相当于是把L里面的全部的元素均丢到这个定义的函数里面去处理。也是处理一个sequence类型的数据。现在好了。我们可以使用一种叫做:list的再构造
>>> [x**2 for x in L]
[1, 4, 9, 16, 25]
哦!!!终于看清楚了庐山真面目了。哈哈~~~
原来还可以写map的哦!
[x**2 for x in L] ===> [1,4,9,16]
首先,这个表达式用[]括起来了,表示这个表达式返回的结果是一个list。其次,后面一部分,也就是for x in L,很明显是把L中的成员依次取出来。第三,前面一部分,也就是x**2,表示对x的操作是"平方"。然后以每次计算后的值作为目标list的成员。其实 可以把这一部分看成是目标list的“通项公式”,通过对这个“通项公式”代入不同的值,可以得到不同的结果。而这个“不同的值”就是由后面的部分,即 for x in L,确定的。
更强大的一个功能:
当然大名顶顶的"list再构造"还有别的功能,它可以加上条件从句(if语句),比如:
- [x**2 for x in L if x%2==0] ===>[4,16]
"list再构造"还可以嵌套for这一部分
看到没有……提取出来的数据还可以带条件提取的哦!!!!强强强
"list再构造"还可以嵌套for这一部分,比如:
- [x*y for x in L for y in L] ===> [1, 2, 3, 4, 2, 4, 6, 8, 3, 6, 9, 12, 4, 8, 12, 16]
做了两个构造处理!python一个字简洁
这个式子已经相当复杂,因此在以程序可读性著称的python世界中,最好不要使用这种东西。不过,也可见用“list再构造”也可以实现for或者map和filter的功能,但是list再构造的效率最高,其次map、filter这些内置函数,再次才是for。
结论:尽可能使用 list再构造!