第六讲:函数(下)
函数(下)
一、lambda(参数,函数体)
1、函数说明:
- lambda语句被用来创建新的函数对象,并且在运行时返回它们。
- Python使用lambda关键字来创建匿名函数。这种函数得名于省略了用def声明函数的标准步骤。
- lambda只是一个表达式,函数体比def简单很多
- lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
- lambda函数拥有自己的名字空间,且不能访问自由参数列表之外后全局名字空间里的参数。
- 虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。
- lambda会返回一个函数对象,但这个对象不会赋给一个标识符,而def则会把函数对象赋值给一个变量(函数名)。
- 像if或for或print等语句不能用于lambda中。
- lambda函数不能共享给别的程序调用,def定义的函数可以
2、语法:
lambda函数的语法只包含一个语句,如下:
lambda [arg1 [, agr2,.....argn]] : expression
3、lambda与函数区别:
#示例1: g=lambda x:x+1 print g(1) #示例2: add=lambda x,y:x+y print add(2,4)
说明:lambda作为一个表达式,定义了一个匿名函数,x为入口参数,x+1为函数体,
用函数表达:
def g(x):
return x+1
print g(1)
练习1:用lambda函数实现字符串指定次数打印,数字与指定数字相乘
#方法一: def make_repeater(n): return lambda s: s*n twice = make_repeater(2) print twice('word') print twice(5) #方法二: data=lambda s,n:s*n print data('hello',3) print data(u'加油!',3) print data(5,3)
二、map(函数,序列)
1、函数说明:
- 将每个列表元素或字符串都执行某个函数
- map的函数操作方法:它将每个字符串或者列表元素,应用某个函数方法,结果返回列表。
- 当seq只有一个时,将函数func作用于这个seq的每个元素上,并得到一个新
- 的seq。
2、单一seq序列
让我们来看一下只有一个seq的时候,map()函数是如何工作的。
从上图可以看出,函数func函数会作用于seq中的每个元素,得到func(seq[n])组成的列表
示例:
>>> map(str,'123') ['1', '2', '3'] >>> map(int,'123') [1, 2, 3] >>> ''.join(map(str,[1,2,3,4])) '1234'
3、多个seq序列
示例1:求两个数的和
r=map(lambda x,y:x+y,[2,3,4],[5,6,7]) print r 运行结果: [7, 9, 11]
示例2:求两个数的和与差
r=map(lambda x,y:(x+y,y-x),[2,3,4],[5,6,7]) print r 运行结果:[(7, 3), (9, 3), (11, 3)]
4、map无法处理seq长度不一致、对应位置操作数类型不一致的情况,这两种情况都会报类型错误。
#当对应位置的数据类型不一致时: res = map(lambda x , y : (x ** y, x + y), [2,4,6],[3,2,'a']) print res 运行结果: Traceback (most recent call last): File "E:/workplace/2019pratice/hanshu.py", line 132, in <module> res = map(lambda x , y : (x ** y, x + y), [2,4,6],[3,2,'a']) File "E:/workplace/2019pratice/hanshu.py", line 132, in <lambda> res = map(lambda x , y : (x ** y, x + y), [2,4,6],[3,2,'a']) TypeError: unsupported operand type(s) for ** or pow(): 'int' and 'str'
#当多个序列的长度不一致时: r = map(lambda x , y : (x ** y, x + y),[2,4,6],[3,2,4,5]) print r
运行结果: Traceback (most recent call last): File "E:/workplace/2019pratice/hanshu.py", line 137, in <module> [2,4,6],[3,2,4,5]) File "E:/workplace/2019pratice/hanshu.py", line 136, in <lambda> r = map(lambda x , y : (x ** y, x + y), TypeError: unsupported operand type(s) for ** or pow(): 'NoneType' and 'int'
三、filter(函数名,需过滤序列)
函数说明:
filter()函数可以对序列做过滤处理,就是说可以使用一个自定的函数过滤一个序列,把序列的每一项传到自定义的过滤函数里处理,并返回结果做过滤。最终一次性返回过滤后的结果。
示例1:过滤列表中大于5小于10的数
def guolvFunc(num): if num>5 and num<10: return num seq=(12,50,8,17,65,14,9,6,14,5) result=filter(guolvFunc,seq) print result
运行结果:
(8, 9, 6)
示例2:过滤1,到10内的所有素数 判断是否是素数:能被自己本身和1整除
import math def getNum(n): check=int(math.sqrt(n)) #math.sqrt函数返回一个数的平方跟 for i in range(2,check+1): if n%i==0: return None return n ret=filter(getNum,range(1,10)) print ret
运行结果:
[1, 2, 3, 5, 7]
四、reduce(二元函数,序列)
函数说明:
reduce内建函数是一个二元操作函数,他用来将一个数据集合(链表,元组等)中的所有数据进行下列操作:
用传给reduce中的函数 func()(必须是一个二元操作函数),先对集合中的第1,2个数据进行操作,得到的结果再与第3个数据用func()函数运算,最后得到一个结果。
示例:
#coding=utf-8 lst = [1,2,3,4,5] print reduce(lambda x,y:x+y,lst)
说明:这种方式用lambda表示当做参数,因为没有提供reduce的第三个参数,所以第一次执行时x=1,y=2,第二次x=1+2,y=3,即列表的第三个元素
方法二:
lst = [1,2,3,4,5] print reduce(lambda x,y:x+y,lst,0) #0表示给x初始化值
说明:
#这种方式用lambda表示当做参数,因为指定了reduce的第三个参数为0,所以第一次执行时x=0,y=1,第二次x=0+1,y=2,即列表的第二个元素, 假定指定reduce的第三个参数为100,那么第一次执行x=100,y仍然是遍历列表的元素,最后得到的结果为115
练习1:使用reduce()计算1~10000所有奇数的和
sum=reduce(lambda x,y:x+y,range(1,10001,2)) print sum
五、eval(字符串)-->表达式
函数说明:eval语句用来计算存储在字符串中的有效Python表达式,并返回计算结果。
示例1:
s='3+4*4' result=eval(s) print result 运行结果: 19
示例2:
def printStr() : print "hello world" return 1 n = eval('printStr()') print n 运行结果: 1
六、exec()与eval()的区别:
函数说明:
从上面exec和eval的讲解中,可以看出,他们都可以动态的执行存储在字符串或文本中的有效的Python表达式,那他们又有什么区别呢?
区别就是 :exec执行的Python语句没有返回值,而eval有返回值。
def printStr() : print "hello world" return 1 print u"***** eval 执行******" print eval('printStr()') print u"***** exec 执行******" exec('printStr()') #加print 则报语法错误
运行结果:
***** eval 执行******
hello world
1
***** exec 执行******
hello world
七、range和 xrange 的区别
函数说明:
range会直接生成一个list对象;
xrange则不会直接生成一个list,而是每次调用返回其中的一个值【xrange返回的是一个生成器】
示例1:
for i in range(2): print i, print for j in xrange(3): print j,
运行结果:
0 1
0 1 2
示例2:有一个分数序列:2/1,3/2,5/3,8/5,13/8,21/13...,求这个数列的前20项之和。
#a,b=a+b,a
a=2.0 b=1.0 sum=0.0 for i in xrange(20): sum+=a/b a,b=a+b,a print sum
运行结果:
21