Python函数式编程笔记

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python函数式编程笔记相关的知识,希望对你有一定的参考价值。

注:慕课网笔记

 

高阶函数                                                                                                          
1.变量可以指向函数,例如 a=abs 则 a(-10)=10 。
2.一个函数可以接收另外一个函数作为参数 例如 fun1 是一个函数 , 函数fun2(fun1 , L) 可以接收 fun1 作为它的一个参数。
  例如:

   1:  
   2: def add(x,y,f)
   3:  return f(1)+f(2) 
   4: add(-1,2,abs) ####相当于是 abs(-1)+abs(-2)

3.如果一个函数可以接收另一个函数作为参数,那么这个函数就是高阶函数。

 

Pyhton 内置高阶函数                                                                                        
1.map()函数
    map()接收一个函数f和一个list,通过函数f依次作用于list每一个元素上,
    得到一个新的元素并返回。
    对于 list [1,2,3,4,5]
    如果希望把list每个元素都作平方就可以用map()函数
例:

def f(x): 
return x*x
print map(f,[1,2,3,4,5])

 

2.reduce()函数
reduce()函数接收的参数和 map()类似,一个函数 f,一个list,
但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,
reduce()对list的每个元素反复调用函数f,并返回最终结果值。


###定义一个函数f,接收x和y,返回x和y的和
def f(x,y):
return x+y

#reduce函数调用f
reduce(f,[1,2,3,4,5])

reduce调用顺序为:
f(1,2)=3  f(3,3)=6 f(6,4)=10 f(10,5)=15 因此reduce函数最终返回结果15。

retuce可以接受第三个参数作为计算初始值
例如:
reduce(f,[1,2,3,4,5],100) 则 f(100,1)=101 f(101,2)=103 f(103,4)=107 f(107,5)=121

综上,因此map返回的是一个list 而 reduce 返回的是一个数值

 

3.filter()
filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False
filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件(true)元素组成的新list。

##利用filter()删除 None 或者空字符串: 
def is_not_empty(s):

return s and len(s.strip())>0
filter(is_not_empty,[‘test‘,None,‘‘,‘str‘,‘
‘,‘END‘ ])


结果:[‘test‘,‘str‘.‘END‘]


### s.strip(rm) 删除 s 字符串中开头、结尾处的 rm 序列的字符。
###
当rm为空时,默认删除空白符(包括‘\n‘,‘\r‘,‘\t‘,‘‘)
###用filter()过滤出1~100中平方根是整数的数,即结果应该是:[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

import math
def is_sqr(x):
i=int(math.sqrt(x))

return x==i*i
print filter(is_sqr, range(1, 101))

 

4.sorted()
sorted()函数可对list进行排序,例如:
sorted([36, 5, 12, 9, 21])
[5, 9, 12, 21, 36]
但同时sorted()也是一个高阶函数,它可以根据一个用户自己定义的比较函数来排序。例如

##定义如下的倒序排序函数 
def reversed_cmp(x, y):
if x > y:

return -1

if x < y:
return 1

return 0
##调用sorted()函数
sorted([36, 5, 12, 9,
21], reversed_cmp)
[36, 21, 12, 9, 5]

 

返回函数的函数                                                                                               

Python的函数不但可以返回int、str、list、dict等数据类型,还可以返回函数
例如,定义一个函数 f(),我们让它返回一个函数 g,可以这样写:

def f(): 
print ‘call f()...‘
#
定义函数g:
def g():

print ‘call g()...‘

# 返回函数g:
return g


我们在函数 f 内部又定义了一个函数 g。由于函数 g 也是一个对象,函数名 g 就是指向函数 g 的变量,
所以,最外层函数 f 可以返回变量 g,也就是函数 g 本身。
返回函数可以把一些计算延迟执行。例如,如果定义一个普通的求和函数
def calc_sum(lst):
    return sum(lst)

调用calc_sum()函数时,将立刻计算并得到结果:
>>> calc_sum([1, 2, 3, 4])
10

但是,如果返回一个函数,就可以“延迟计算”:

def calc_sum(lst): 
def lazy_sum():

return sum(lst)

return lazy_sum

# 调用calc_sum()并没有计算出结果,而是返回函数:
>>> f = calc_sum([1, 2, 3, 4])
>>> f
<function lazy_sum at 0x1037bfaa0>
# 对返回的函数进行调用时,才计算出结果:
>>> f()
10
由于可以返回函数,我们在后续代码里就可以决定到底要不要调用该函数。

 

闭包                                                                                                             
内层函数引用外层变量然后返回内层函数的情况,称为闭包
闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,
就要确保引用的局部变量在函数返回后不能变。


# 希望一次返回3个函数,分别计算1x1,2x2,3x3:
def count():
fs = []

for i in range(1, 4):

def f():


return i*i
fs.append(f)

return fs
f1, f2, f3 = count()
#
实际结果是f1()f2()f3()都是9,原因是count()函数返回三个函数,执行完count()之后这三个函数
#
引用的变量i已经变成了3,所以当调用f1()f2()f3()时返回值都是9.

解决方法:
#solution1 :函数fun()它可以正确地返回一个闭包g,g所引用的变量j不是循环变量,因此将正常执行


def count():
fs = []
for i in
range(1, 4):
def fun(i):

def g():


return i*i

return g

fs.append(fun(i))

return fs
f1, f2, f3 = count()
print f1(), f2(), f3()

#solution2 :函数定义时可以获取到i,问题便可解决。而默认参数正好可以完成定义时获取i值
#并且运行函数时无需参数输入的功能,所以在函数f()定义中改为f(m = i),函数f返回值改为m*m即可

def count(): 
fs = []
for i in
range(1, 4):
def f(m = i):

return m
* m
fs.append(f)

return fs
f1, f2, f3 = count()
print f1(), f2(),
f3()

 

匿名函数                                                                                                            

高阶函数可以接收函数作为参数,有时候我们不需要显示定义函数,直接传入匿名函数更加方便简洁。
前面提到的map()函数可以接收一个函数f和一个list

#lambda是关键字,表示匿名函数,冒号前面的x表示函数参数,这里lambda x:x*x
#实际上就是def(x):
#          return x*x
>>>map(lambda x: x * x, [1, 2, 3, 4, 5, 6, 7, 8, 9])
[1,4,9,16,25,36,49,64,81]

匿名函数返回值就是:后面的表达式的值,而匿名函数仅能有一个表达式,不用写return。
返回函数的时候也可以返回匿名函数:
>>> myabs = lambda x: -x if x < 0 else x
>>> myabs(-1)
1
>>> myabs(1)
1

 

装饰器                                                                                                            
装饰器可以对一个函数、方法或者类进行加工
首先我们自己定义一个sum函数

def sum(a,b) 
print a+b


之后我们又希望在原来的基础上加上一个打印输入的功能,像下面这样:

def sum(a,b) 
print ("input:",a,‘,‘,b)

print a+b

可以直接修改sum函数的代码,也可以通过装饰器来实现,

 
def decorator(F):
def
new_F(a, b):
print("input", a, b)

return F(a, b)

return new_F


之后再通过调用装饰器f=decorator(f)
python为我们提供了一个简便的语法

@decorater 
def sum(a,b)
print a+b


那么在右面调用sum()函数的时候就可以有打印输入的功能了
上面的例子我们可以看出Python的装饰器实际上就是高阶函数。接收一个函数作为参数返回一个新函数。
不过在编写装饰器的时候一般会写 参数(*args,**kw) 表示接收函数f的任意参数以及 @functools.wraps(f)
来完善装饰器。因为仅仅经过装饰其改造后的函数与原函数相比__name__变量(也就是函数名)也变化了

def decorater(f) 
@functools.wraps(f)

def wrapper(*args,**kw):

print ‘call %s ...‘ % f.__name__

return f(*args,**kw)

return wrapper

带参数的decorator


import time
def performance(unit):
def
perf_decorator(f):
def
wrapper(*args,**kw):


t1=time.time()


r=f(*args,**kw)


t2=time.time()

t=
(t2-t1) * 1000 if unit==‘ms‘ else (t2-t1)

print
‘call %s() in %f %s‘ % (f.__name__,t,unit)

return r

return wrapper

return perf_decorator
@performance(‘ms‘)
def factorial(n):
return
reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)


上面的performance装饰器的功能是打印函数执行的时间,它接受一个参数unit
可以根据传入的参数unit来表示打印时间的单位是ms还是s。
偏函数:
int()函数还提供额外的base参数,默认值为10。如果传入base参数,就可以做 N 进制的转换
假设要转换大量的二进制字符串,每次都传入int(x, base=2)非常麻烦,于是,我们想到,
可以定义一个int2()的函数,默认把base=2传进去,像下面这样:

def int2(x, base=2): 
return int(x, base)


functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用
下面的代码创建一个新的函数int2
>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2(‘1000000‘)
64
所以,functools.partial可以把一个参数多的函数变成一个参数少的新函数,少的参数需要在创建时
指定默认值,这样,新函数调用的难度就降低了。

以上是关于Python函数式编程笔记的主要内容,如果未能解决你的问题,请参考以下文章

笔记效率之门——Python中的函数式编程技巧

python学习笔记011——函数式编程

python笔记5:函数式编程

Python学习笔记五函数式编程

python学习笔记---函数式编程

Python学习笔记五函数式编程