一、函数式编程
- 函数式编程:
采用一系列高阶函数来解决问题,是一种面向过程的实现,数据经过函数不断输入输出处理。纯函数式编程参数是没有变量的且输出固定。 - 高阶函数:
函数的参数能够接收变量 and 变量可以指向函数。----->函数作为参数输入 or 函数作为结果输出。
例如:内置函数、函数闭包、递归函数、装饰器。
f=abs
print abs(-10)
print f(-10)
result:
10
10
def _countPingfang_(num):
return num**2
def _pingfangHe_(x,y,f=_countPingfang_):
return f(x)+f(y)
print _pingfangHe_(3,4)
result:
25
- python实现了部分函数式编程,允许输入有变量且输出结果可变。
二、内置高阶函数
2.1 lambda函数
- lambda意为匿名函数。也称为lambda表达式。
- 语法格式:
lambda 参数:表达式
,例如:lambda x,y:x+y
a = lambda x,y,z=100:x+y+z
print a(5,10)
result:
115
b=lambda *args,**kwargs:args
c=lambda *args,**kwargs:kwargs
print b("2019","1","11",name="tyson",sex="boy")
print c("2019","1","11",name="tyson",sex="boy")
result;
('2019', '1', '11')
{'name': 'tyson', 'sex': 'boy'}
2.2 map函数
- map函数将参数1(函数)作用在参数二(可迭代对象)的每个元素上,然后创建由作用过后的元素组成的返回值列表。
- 当然这也可以通过列表解析式来实现
[ expression for i in list Judgement sentence]
。
案例1:
def _countPingfang_(x):
return x**2
list=range(1,10)
list1=[x**2 for x in list]
list2=map(_countPingfang_,list)
print list
print list1
print list2
result:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 4, 9, 16, 25, 36, 49, 64, 81]
[1, 4, 9, 16, 25, 36, 49, 64, 81]
案例2:将列表中的元素转换成规范的大小写(也就是只有首字母大写)。这里需要注意到的两个点:需要用到lambda函数而且lambda函数的传输参数应该为一个字符串而不是一个列表。**因为map函数的特性就是将可迭代对象的每一个元素都经过lambda函数的。注意到将函数作文参数时还有需不需要加括号的问题。
nameList = ['LaoWang','laoli','laochEn']
print nameList
print map(lambda nameString:nameString.title(),nameList)
result:
['LaoWang', 'laoli', 'laochEn']
['Laowang', 'Laoli', 'Laochen']
2.3 reduce函数
接收的参数和map函数相同,一个函数一个可迭代对象,不同的是reduce函数将可迭代对象中的两个元素先放入函数中运算得到返回值,再和可迭代对象中的下一个元素放入函数中进行运算,直到结束。(经过测试,函数只能由两个参数)
案例1:
def func(x,y):
return x+y
list=[1,2,3,4,5]
print reduce(func,list)
result:
15
上面的例子也相当于func(func(func(func(1,2),3),4),5)
案例2:将数字列表转换成数
def _transfer_(x,y):
return x*10+y
num=[1,2,3,8,0]
print reduce(_transfer_,num)
result:
12380
案例3:字符串类型的数字转换成数字的实现
def _strToint_(s):
def strToList(s):
return map(lambda s:{'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}[s],s)
temp1 = strToList(s)
return reduce(lambda x,y:x*10+y,temp1)
print _strToint_('159891')
result:
159891
案例3的lambda函数简化实现
numString='156789'
print reduce(lambda x,y:x*10+y,map(lambda s:{'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9}[s],numString))
案例4:编写一个prod()函数,可以接收list并利用reduce()求积(假设list内的都是整型数字而不是字符型数字)
def prod(numList):
return reduce(lambda x,y:x*y,numList)
print prod([1,2,3])
print prod([1,2,3,5,6])
print prod([1,2,3,4])
result:
6
180
24
2.4 filter函数
filter函数是一个过滤函数,根据函数返回值True或者False来决定是否保留列表中的元素。语法格式:filter(funcName,list)
。
案例1:
尝试使用filter()保留1~00的素数。
def _ifzhishu_(num):
if num ==1:
return False
else:
for i in range(2,num-1):
if num%i==0:
return False
else:
return True
print filter(_ifzhishu_,range(1,101))
result:
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
三、返回函数
3.1 定义
函数作为结果被返回。需要注意的是:map这类函数是将函数作为输入而不是输出。
定义形式:
def outsidefunc():
statements
def insidefunc():
return var
return insidefunc
可以先查看一下,return回来的是什么
print type(outsidefunc)
result:
<type 'function'>
所以,这么做的好处就是,函数的调用形式不变,但是将函数赋值给变量时,若有参数需要先指定好参数。
def outsidefunc(x):
def insidefunc():
return x**2
return insidefunc
a=outsidefunc(100)
print a()
def outsidefunc2():
def insidefunc():
print "test2"
return insidefunc
b=outsidefunc2()
b()
3.2 闭包
在一个内部函数里,对外部作用域的变量进行引用**(不是全局作用域)。那么这个内部函数就是闭包**。
案例:简单的闭包
def outsidefunc(x):
def insidefunc():
return x**2
return insidefunc
a=outsidefunc(100)
print a()
result:
10000
四、装饰器
4.1 定义和用处
- 装饰器采用函数作为参数,可以在不修改原函数结构的情况下为函数增加功能。
- 装饰器是闭包的高阶应用,我们可以这么来理解:
首先,闭包是内部函数调用非全局变量的外部变量,比如这样:
def outsidefunc(x):
def insidefunc():
return x**2
return insidefunc
a=outsidefunc(100)
print a()
我们将外部函数的参数x换成一个函数func()
#coding:UTF-8
def decorator(func):
def insidefunc():
#需要为函数添加的功能语句
print "这是装饰器为函数新添加的语句"
return func()
return insidefunc
def f1():
print "这是原函数f1"
@decorator
def f2():
print "这是另一个经过装饰器加工的函数f2"
f1()
print "\n"
f2()
result:
这是原函数f1
这是装饰器为函数新添加的语句
这是另一个经过装饰器加工的函数f2
上面的例子就是闭包的应用,也就是说需要经过装饰器装饰的函数,应该在其函数定义的上面加上@装饰器名称
4.2 无参数装饰器修饰有参数函数
#coding:UTF-8
def decorator(func):
def insidefunc():
#需要为函数添加的功能语句
print "这是装饰器为函数新添加的语句"
return func()
return insidefunc
其实最重要的是,我们要明白func
变量代表着原函数,insidefunc
才是真正意义上的原函数本体。所以真正需要和原函数参数保持一致的则是insidefunc
。所以我们将def insidefunc():
改成def insidefunc(*args,**kwargs):
就可以在真正的原函数本体里面使用源函数的参数了。当然,能这么做是因为我们拿到形参func
(也就是实参原函数
。根据闭包,我们在内部函数insidefunc
里可以使用外部变量作用域的变量func
。
实例:
#coding:UTF-8
def decorator(func):
def insidefunc(*args,**kwargs):
'''假设该装饰器的作用是打印出每一个被装饰器加工的函数的输入变量'''
print args,kwargs
return func()
return insidefunc
@decorator
def f1(*args,**kwargs):
# statements
pass
@decorator
def f2(*args,**kwargs):
# statements
pass
f1("tyson",21)
f2("laowang","niubi",age="10")
result:
('tyson', 21) {}
('laowang', 'niubi') {'age': '10'}
4.3 有参数装饰器修饰函数
根据上面我们知道,原函数的本体是insidefunc
,那要给参数器加参数的话,需要再加一层函数,用来传入装饰器的参数,否则根本无法拿到不同函数使用装饰器时传递的不同的装饰器函数。
实例:
#coding:UTF-8
def outside(date,state="success"):
def decorator(func):
def insidefunc(*args,**kwargs):
print "这是原函数被调用时就有的参数:"
print args,kwargs
print "该函数的装饰器的测试时间", date
print "该函数的装饰器的测试状态", state
print "\n"
return func()
return insidefunc
return decorator
@outside("20190120",state="failed")
def f1(*args,**kwargs):
# statements
pass
@outside("20190120")
def f2(*args,**kwargs):
# statements
pass
f1(name="f1")
f2(name="f2")
4.4 用多个装饰器修饰函数
#coding:UTF-8
def outside1(decoratorname,date,state="success"):
def decorator(func):
def insidefunc(*args,**kwargs):
print "这是原函数被调用时就有的参数:"
print args,kwargs
print "所使用的装饰器是:", decoratorname
print "该函数的装饰器的测试时间", date
print "该函数的装饰器的测试状态", state
print "\n"
return func()
return insidefunc
return decorator
def outside2(decoratorname,date,state="success"):
def decorator(func):
def insidefunc(*args,**kwargs):
print "这是原函数被调用时就有的参数:"
print args,kwargs
print "所使用的装饰器是:", decoratorname
print "该函数的装饰器的测试时间", date
print "该函数的装饰器的测试状态", state
print "\n"
return func()
return insidefunc
return decorator
@outside1("第一个装饰器","20190120",state="failed")
@outside2("第二个装饰器","20190120",state="failed")
def f1(*args,**kwargs):
# statements
pass
f1(name="f1")
这里需要注意的是,若使用了多个装饰器,则原函数的参数只会传递给第一个装饰器。
五、递归函数
若函数内部调用自身,这个函数就是递归函数
实例:求阶乘
#coding:UTF-8
def jie(num):
temp=1
while num>1:
temp*=num
num-=1
jie(num)
return temp
print jie(5)
六、生成器
- 所谓生成器,就是带有yield语句的函数。生成器允许函数返回一个值然后挂起直到下次调用。
- 生成器可以节省内存空间,使得函数结果散落在不同的时间请求上。
- 生成器包括三部分:生成器函数
def func(*args,**kwargs): statements;yield something
、生成器对象a=func(*args,**kwargs)
、生成器调用方法next()
实例:
#coding:UTF-8
def pingfanghe(numList):
for i in numList:
yield i**2
test1=pingfanghe([1,2,3])
print next(test1)
print next(test1)
print next(test1)