Python函数式编程实例详解
作者:theVicTory 发布时间:2023-02-26 21:26:31
本文实例讲述了Python函数式编程。分享给大家供大家参考,具体如下:
函数式编程就是一种抽象程度很高的编程范式,从计算机硬件->汇编语言->C语言->Python抽象程度越高、越贴近于计算,但执行效率也越低。纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!
Python对函数式编程提供部分支持,支持高阶函数(函数可以作为变量传入),支持闭包(返回一个函数),有限地支持匿名函数。由于Python允许使用变量,因此,Python不是纯函数式编程语言。
1、高阶函数
即可以通过变量名指向函数,函数通过变量名作为参数传给另一个函数,并通过变量名来使用。例如下面将开方函数math.sqrt作为参数传递给变量f,变量名f就指向了函数math.sqrt,再通过变量f使用该函数给x、y开方。
import math
def add(x, y, f):
return f(x) + f(y) # 函数作为参数传递给f来调用
res = add(25, 9, math.sqrt)
print(res)
map函数接收一个函数 f 和一个 list,并把函数 f 依次作用在 list 的每个元素上,得到一个iterators并返回。
def format_name(s):
return s[0].upper()+s[1:].lower() #将列表的每个元素首字母大写,其他小写
print(list(map(format_name, ['adam', 'LISA', 'barT'])))
#输出:['Adam', 'Lisa', 'Bart']
filter()根据判断函数f的结果自动过滤掉不符合条件的元素,以iterators返回剩下的元素
def is_odd(x):
return x % 2 == 1 # 过滤函数,x为奇返回True
f_res = filter(is_odd, [1, 4, 6, 7, 9, 12, 17])
print(list(f_res)) # 输出过滤后的结果list:1 7 9 17
sorted()函数用于对可迭代的对象进行排序,参数key=指定排序的关键字,这里可以借助functools.cmp_to_keys()将比较方法映射为自定义的方法。例如实现了降序排列,比较函数cmp返回值 -1 代表a 应该排在 b 的前面,如果a排在b 的后面返回 1。如果 a、b相等返回 0。
import functools
def cmp(a, b):
if b < a:
return -1
if a < b:
return 1
return 0
a = [1, 2, 5, 4]
print(sorted(a, key=functools.cmp_to_key(cmp)))
2、匿名函数和闭包
有时函数简单到只有一个表达式时,为了简化代码可以使用匿名函数来代替,匿名函数一般形式为lambda 参数:返回表达式,例如lambda x:x*x,就是传入x参数并返回x的平方。例如在使用map()函数时需要传入一个函数用于list的元素,此时可以使用匿名函数作为参数
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]
res = map(lambda x: x * x, lst) # 将匿名函数作用于lst
print(list(res))
函数的闭包(Closure)是指内层函数引用了外层函数的变量,然后将内层函数像变量一样返回的情况。例如函数calc_prod()接收一个list,在其内部定义一个函数multiply,计算list元素的乘积并将multiply返回。用f接收calc_prod()的返回函数,并在之后调用该函数
def calc_prod(lst):
def multiply():
res=1
for i in lst:
res=res*i
return res
return multiply # 将函数返回
f = calc_prod([1, 2, 3, 4]) # 接收返回函数
print(f()) # 调用返回函数
注意在函数闭包时要确保引用的局部变量在函数返回后不能变。例如下面的例子,当count()函数返回3个函数时,由于f1、f2、f3并没有被调用,所以并未计算 i*i。当 f1 被调用时,这3个函数所引用的变量 i 的值已经变成了3,所以此时使用的变量i的值已经发生了改变,三个函数的输出都是9。
def count():
fs = []
for i in range(1, 4):
def f():
print(i) # 函数f1()调用时i已经变为3
return i*i
fs.append(f)
return fs
f1, f2, f3 = count()
print(f1()) # 输出9而不是1
3、函数装饰器
函数装饰器是指在原有函数的基础上对函数作修改和装饰操作。其基本思想是,既然函数可以像变量一样作为参数传入并且返回,那么我们可以将原来的函数传入装饰器函数,然后增加我们需要的操作,之后在将原函数返回出来。
例如下面定义了一个装饰器log用于打印函数名称,原函数作为参数f传入。在装饰器中定义新的函数fn,其中参数列*args和**kw代表自适应参数个数,防止不同参数个数的函数在使用装饰器时不匹配。在新函数fn中输出原函数的名称,之后将原函数原封不动地调用一遍并返回出去。最后返回新函数。
在使用装饰器时,只需要在函数的定义前加一行@装饰器名
def log(f): # 定义装饰器log
def fn(*args, **kw): # 定义新函数
print('函数名: ' + f.__name__) # 打印函数名
return f(*args, **kw) # 在新函数中调用原函数并返回结果
return fn # 返回新函数
@log # 为函数add添加装饰器
def add(x, y):
return x + y
print(add(1, 2))
如果希望给装饰器传入一个参数,则需要定义三重嵌套的函数,在最外层增加一层函数用于接收参数。例如希望在打印函数名之前输出传入的参数“DEBUG”
def log(prefix):
def log_decorator(f):
def wrapper(*args, **kw):
print '[%s] %s()...' % (prefix, f.__name__)
return f(*args, **kw)
return wrapper
return log_decorator
@log('DEBUG') # 为装饰器传入参数
def test():
pass
test()
由于装饰器实际上是创建了新的函数fn并替代了原函数,所以原函数的相关信息例如函数名会被覆盖,可以用@functools.wraps(f)来复制原函数的信息以保留下来。
import functools
def log(f):
@functools.wraps(f)
def fn(*args, **kw):
print 'call...'
return f(*args, **kw)
return fn
偏函数可以为函数填上一个固定的参数值,从而生成一个新的函数。例如原函数add需要两个参数x、y,通过指定y=1得到偏函数add1,这个函数只需要输入一个参数x,从而计算x+1的值。
import functools
def add(x, y):
return x + y
add1 = functools.partial(add, y=1)
print(add2(3)) # 输出结果为4
关于Python相关内容感兴趣的读者可查看本站专题:《Python函数使用技巧总结》、《Python面向对象程序设计入门与进阶教程》、《Python数据结构与算法教程》、《Python字符串操作技巧汇总》、《Python编码操作技巧总结》及《Python入门与进阶经典教程》
希望本文所述对大家Python程序设计有所帮助。
来源:https://blog.csdn.net/theVicTory/article/details/95070465
猜你喜欢
- 对于小型站点,使用七牛云存储的免费配额已足够为站点提供稳定、快速的存储服务七牛云存储已有Python SDK,对它进行简单封装后,就可以直接
- 我们开发数据库应用时,常常需要用到模糊查询。如果同一个条件需要匹配很多字段怎么办呢?通常,程序员会每个字段都在SQL中“field like
- 下面是虚机维护中,经常碰到的一些ASP程序中的数据库调用的错误,现收集整理如下:
- 程序的功能有了个大体的框架,其实可以自己添加一些功能,比如开始的数据库连接 ,可以先设置变量然后通过INIT() 来选择
- 原始需求:例如有一个列表:l = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]希望把它转换成下面这种形式:[1, 2,
- Python 是面向对象的语言,所以程序抛出的异常也是类。常见的异常类1.NameError:尝试访问一个没有申明的变量2.ZeroDivi
- 在实现TextStraem的时候,找到判断文件编码的代码是VBS的,但是在JScript中是没有ASC等函数的,也不能对二进制数据进行处理,
- 大家好,我是丁小杰。上次和大家分享了Python定时爬取微博热搜示例介绍,堪称摸鱼神器,一个热榜不够看?今天我们再来爬取一下抖音热搜榜,感兴
- 申明如下:1 本着大家都学习的目的,我们只研究官方对应的4.0板本,请大家注意尊重开发者,保护知识产权,商业使用,请到官方购买正板!2 文章
- 在ASP输出页面只是调出数据库里内容展现给用户看没有使用SESSION等动态属性,是可以CACHE的,以加快访问速度具体操作方法如下:在as
- 现状≠将来?程序员做设计本身就很悲哀,纠结于客户与坚持之间就更是如此。无论我今后的路会怎么走,我想始终不变的事情就是与客户博弈了。无论是放弃
- 本文实例讲述了Python实现数通设备端口使用情况监控的方法。分享给大家供大家参考。具体如下:最近因工作需要,上面要求,每天需上报运维的几百
- 第一招、mysql服务的启动和停止net stop mysqlnet start mysql第二招、登陆mysql语法如下: mysql -
- 关于采集-防采集的我想大家都很清楚。这个就不多说,采集最终还是从页面源代码入手,所以只要没有规律想采集就难!由于一天自己在策划某个网站的时候
- 前言上回说到我们如何把拉勾的数据抓取下来的,既然获取了数据,就别放着不动,把它拿出来分析一下,看看这些数据里面都包含了什么信息。(本次博客源
- 如下所示:import cv2import os#图片路径im_dir = '/home/suanfa/data/out/20170
- win7以上需要使用管理员权限操作。# -*- coding: utf-8 -*-import osimport globimport sh
- Python慢的重要原因:1、python是动态性语言不是静态性语言在python程序执行的时候,编译器不知道变量的类型。2、python是
- 异常是指因为程序出现了错误而在正常控制流以外采取的行动,其分为两个阶段,第一阶段是引发异常的错误,当系统检测到错误并且意识到异常条件,解释器
- 前言:Python中for循环和while循环本质上是没有区别的,但是在实际应用上,针对性不太一样。for循环,主要应用在遍历中,体现的是遍