Python学习笔记(四)
来源:互联网 发布:通信算法工程师 工作 编辑:程序博客网 时间:2024/05/16 19:10
Python学习笔记(四)
函数式编程
函数式编程就是一种抽象程度很高的编程范式,函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
1.高阶函数
将函数作为参数的函数叫高阶函数。一个简单的高阶函数:
def add(x, y, f): return f(x) + f(y)
几个Python内置的高阶函数:
map
map()
函数接收两个参数,一个是函数,一个是Iterable
。map
将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator
返回。通俗点说,传一个函数和一个list进去后,函数作用于list里面的每一个元素之后返回一个新的list。
L= [1,2,3,4,5]def f(x): return x * xm = map(f,L)print(list(m))print(L) [1, 4, 9, 16, 25][1, 2, 3, 4, 5]
由于map()
返回的是Iterable
对象,因此通过list()
函数让它把整个序列都计算出来并返回一个list。
reduce
reduce()
把一个函数作用在一个序列[x1, x2, x3, ...]
上,这个函数必须接收两个参数,reduce()
把结果继续和序列的下一个元素做累积计算
from functools import reducedef fn(x,y): return x*10 + yprint(reduce(fn,[1,3,5,7,9])) 13579
filter
filter()
函数用于过滤序列,和map()
类似,filter()
也接收一个函数和一个序列。和map()
不同的是,filter()
把传入的函数依次作用于每个元素,然后根据返回值是True
还是False
决定保留还是丢弃该元素。
def is_odd(x): return x%2 == 1L = list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))print(L) [1, 5, 9, 15]
删除一个序列中的空元素,相当于过滤一个序列,用到函数strip()
def not_empty(s): return s and s.strip()L = list(filter(not_empty, ['A', '', 'B', None, 'C', ' ']))print(L) ['A', 'B', 'C']
sorted
sorted()
函数是用来对序列进行排序的函数
print(sorted([36, 5, -12, 9, -21])) [-21, -12, 5, 9, 36]
同时它也是一个高阶函数,它还可以接收一个key
函数来实现自定义的排序
print(sorted([36, 5, -12, 9, -21], key=abs)) [5, 9, -12, -21, 36]
要进行反向排序,不必改动key函数,可以传入第三个参数reverse=True
:
print(sorted([36, 5, -12, 9, -21], key=abs,reverse = True)) [36, -21, -12, 9, 5]
2.返回函数
函数作为返回值
高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。
def lazy_sum(*args): def sum(): ax = 0 for x in args: ax = ax + x return ax return sumf = lazy_sum(1,2,3,4,5)print(f)print(f()) 显示结果:<function lazy_sum.<locals>.sum at 0x00342030>15
由上可知,当调用lazy_sum()
的时候,返回的是求和函数,当调用f()
的时候才进行求和
闭包
在上面的例子中,在函数lazy_sum
中又定义了函数sum
,并且,内部函数sum
可以引用外部函数lazy_sum
的参数和局部变量,当lazy_sum
返回函数sum
时,相关参数和变量都保存在返回的函数中,这种结构叫闭包
当我们调用lazy_sum()
时,每次调用都会返回一个新的函数,即使传入相同的参数:
f1 = lazy_sum(1,2,3,4,5)f2 = lazy_sum(1,2,3,4,5)print(f1)print(f2) 运行结果: <function lazy_sum.<locals>.sum at 0x009C2030><function lazy_sum.<locals>.sum at 0x00A17E88>
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量
如果一定要引用循环变量怎么办?方法是再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变。
3.匿名函数
匿名函数,就是没用名字的函数,即不需要显示定义。在Python中,对匿名函数提供了有限支持。
f = map(lambda x : x * x ,[1,2,3,4,5])print(list(f)) 运行结果: [1, 4, 9, 16, 25]
关键字lambda
表示匿名函数,冒号前面的x
表示函数参数。
匿名函数有个限制,就是只能有一个表达式,不能写return,返回值就是该表达式的结果。
匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:
f = lambda x : x * xprint(f(5)) 运行结果: 25
同样,也可以把匿名函数作为返回值返回。
4.装饰器
装饰器的作用是在不修改原来函数的基础上增强函数功能。装饰器也是一个函数,这个函数是将装饰的函数作为参数,并且返回一个函数,定义一个装饰器:
def deco(func): print("call deco()") def wrapper(): print("call wrapper()") func() return wrapper
deco
函数为装饰器函数,func
为被装饰的函数,它被当作参数传入到装饰器中。
借助Python的@
语法,把decorator置于函数的定义处:
@decodef bar(): print("call bar()")
现在调用bar()
,打印结果如下:
bar() 运行结果: call deco()call wrapper()call bar()
由打印结果可以看出函数的执行顺序:deco–>wrapper–>bar。过程如下:
def deco(func): print("call deco()") def wrapper(): print("call wrapper()") func() return wrapper@decodef bar(): print("call bar()")运行结果: call deco()
由于@deco
语法作用,它相当于执行一句代码:
bar = deco(bar)
它会先调用deco()
函数,并将被装饰的函数作为参数传进去,此时bar指向了deco()
函数返回的函数wrapper()
,bar()
函数本身还是存在的。而当调用bar()
这句代码的时候相当于调用了wrapper()
函数,而在wrapper()
内部又调用了bar()
,因此函数的执行顺序就是成了deco–>wrapper–>bar。
装饰器的本质就是对闭包的使用。
5.偏函数
此处的偏函数不是数学意义上的偏函数,而是functools
模板提供的一个功能,主要作用是降低函数调用的难度。
高阶函数sorted()
可以对一个序列进行排序。现在有一个 ['bob', 'about', 'Zoo', 'Credit']
,用sorted()
对其进行排序 :
print(sorted(['bob', 'about', 'Zoo', 'Credit'])) 运行结果: ['Credit', 'Zoo', 'about', 'bob']
现在需求是忽略大小写进行排序,这样我们就需要定义一个函数传入到sorted()
函数里面去:
def f(str): return str.lower() print(sorted(['bob', 'about', 'Zoo', 'Credit'],key = f)) 运行结果: ['about', 'bob', 'Credit', 'Zoo']
functools.partial
就是帮助我们创建一个偏函数的,不需要我们自己定义函数f:
import functoolsf= functools.partial(sorted,key = str.lower)print(f(['bob', 'about', 'Zoo', 'Credit'])) 运行结果: ['about', 'bob', 'Credit', 'Zoo']
当函数的参数个数太多,需要简化时,使用functools.partial
可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。
参考资料:廖雪峰的官方网址
- Python学习笔记(四)
- python学习笔记(四)
- Python学习笔记(四)
- python学习笔记(四)
- Python学习笔记(四)
- python 学习笔记(四)
- python学习笔记(四)
- Python学习笔记(四)
- Python学习笔记(四)
- Python学习笔记(四)
- python学习笔记(四)
- python学习笔记(四)
- python学习笔记(四)
- python学习笔记(四)
- python学习笔记(四)
- Python学习笔记(四)
- Python学习笔记(四)
- Python学习笔记(四)
- html中插入javascript画矩形
- str2float
- JVM学习(初识JVM)
- 雷军说小米6下月起不再耍猴 你信吗?
- 作业批处理
- Python学习笔记(四)
- oracle克隆安装(转)
- 开发中遇到的坑.
- Docker
- libiec61850系列:建模(二)
- oracle静默安装
- NOIP2010 烽火传递 队列DP
- List快速按照指定顺序排列
- ajax与servlet交互(通过JSON),JAVA的arraylist传到前端的方法