浅谈Python 函数式编程


Posted in Python onJune 20, 2020

匿名函数lambda表达式

什么是匿名函数?

匿名函数,顾名思义就是没有名字的函数,在程序中不用使用 def 进行定义,可以直接使用 lambda 关键字编写简单的代码逻辑。lambda 本质上是一个函数对象,可以将其赋值给另一个变量,再由该变量来调用函数,也可以直接使用。

#平时,我们是先定义函数,再进行调用
def power(x):
 return x ** 2

print(power(2))

#使用lambda表达式的时候,我们可以这样操作
power = lambda x : x ** 2
print(power(2))

#觉得太麻烦,还可以这样调用
print((lambda x: 2 * x)(8))

lambda表达式的基本格式:lambda 入参 : 表达式

#入参可以有多个,比如 
power = lambda x, n: x ** n

print(power(2, 3))

lambda 表达式的使用场景

一般适用于创建一些临时性的,小巧的函数。比如上面的 power函数,我们当然可以使用 def 来定义,但使用 lambda 来创建会显得很简洁,尤其是在高阶函数的使用中。

定义一个函数,传入一个list,将list每个元素的值加1

def add(l = []):
 return [x +1 for x in l]

print(add([1,2,3]))

上面的函数改成将所有元素的值加2

可能大家会说,这还不简单,直接把return里的1改成2就行了。但是真的行吗?如果函数被多个地方使用,而其他地方并不想加2,怎么办?

这好办,把变得那部分抽出来,让调用者自己传

def add(func,l = []):
 return [func(x) for x in l]

def add1(x):
 return x+1

def add2(x):
 return x+2

print(add(add1,[1,2,3]))
print(add(add2,[1,2,3]))

一个简简单单的问题,一定要用这么多代码实现?

def add(func,l = []):
 return [func(x) for x in l]

print(add(lambda x:x+1,[1,2,3]))
print(add(lambda x:x+2,[1,2,3]))

map函数

map的基本格式

map(func, *iterables)

map() 函数接收两个以上的参数,开头一个是函数,剩下的是序列,将传入的函数依次作用到序列的每个元素,并把结果作为新的序列返回。也就是类似 map(func,[1,2,3])

同样的,我们还是来完成这样一个功能:将list每个元素的值加1

def add(x):
 return x + 1

result = map(add, [1, 2, 3, 4])
print(type(result))
print(list(result))

使用lambda表达式简化操作

result = map(lambda x: x + 1, [1, 2, 3, 4])
print(type(result))
print(list(result))

函数中带两个参数的map函数格式

使用map函数,将两个序列的数据对应位置求和,之后返回,也就是对[1,2,3],[4,5,6]两个序列进行操作之后,返回结果[5,7,9]

print(list(map(lambda x, y: x + y, [1, 2, 3], [4, 5, 6])))

对于两个序列元素个数一样的,相对好理解。如果两个序列个数不一样的,会不会报错?

print(list(map(lambda x, y: x + y, [1, 2, 3], [4, 5])))

我们可以看到不会报错,但是结果以个数少的为准

reduce函数

reduce函数的基本格式

reduce(function, sequence, initial=None)

reduce把一个函数作用在一个序列上,这个函数必须接收两个参数,reduce函数把结果继续和序列的下一个元素做累积计算,跟递归有点类似,reduce函数会被上一个计算结果应用到本次计算中

reduce(func, [1,2,3]) = func(func(1, 2), 3)

使用reduce函数,计算一个列表的乘积

from functools import reduce

def func(x, y):
 return x * y

print(reduce(func, [1, 2, 3, 4]))

结合lambda表达式,简化操作

from functools import reduce

print(reduce(lambda x, y: x * y, [1, 2, 3, 4]))

filter 函数

filter 顾名思义是过滤的意思,带有杂质的(非需要的数据),经过 filter 处理之后,就被过滤掉。

filter函数的基本格式

filter(function_or_None, iterable)

filter() 接收一个函数和一个序列。把传入的函数依次作用于每个元素,然后根据返回值是 True 还是 False 决定保留还是丢弃该元素。

使用 filter 函数对给定序列进行操作,最后返回序列中所有偶数

print(list(filter(lambda x: x % 2 == 0, [1, 2, 3, 4, 5])))

sorted 函数

sorted从字面上就可以看去这是个用来排序的函数,sorted 可以对所有可迭代的对象进行排序操作

sorted的基本格式

sorted(iterable, key=None, reverse=False)

#iterable -- 可迭代对象。
#key -- 主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序。
#reverse -- 排序规则,reverse = True 降序 , reverse = False 升序(默认)。 

#对序列做升序排序
print(sorted([1, 6, 4, 5, 9]))

#对序列做降序排序
print(sorted([1, 6, 4, 5, 9], reverse=True))

#对存储多个列表的列表做排序
data = [["Python", 99], ["c", 88]]
print(sorted(data, key=lambda item: item[1]))

闭包

在万物皆对象的Python中,函数是否能作为函数的返回值进行返回呢?

def my_power():
 n = 2
 def power(x):
  return x ** n
 return power

p = my_power()
print(p(4))

#------------------------------------------------------------
def my_power():
 n = 2
 def power(x):
  return x ** n
 return power

n = 3
p = my_power()
print(p(4))

我们可以看到,my_power 函数在返回的时候,也将其引用的值(n)一同带回,n 的值被新的函数所使用,这种情况我们称之为闭包

当我们把n的值移除到my_power函数外面,这个时候来看下计算结果

n = 2

def my_power():
 def power(x):
  return x ** n
 return power

n = 3
p = my_power()
print(p(4))

为什么输出的结果会是64?

我们先来看看闭包时,p.__closure____的结果

#例1
def my_power():
 n = 2
 def power(x):
  return x ** n
 return power

p = my_power()
print(p.__closure__)

#结果:(<cell at 0x00000264518F9A38: int object at 0x00007FFA7F617120>)
#closure是内部函数的一个属性,用来保存环境变量

#---------------------------------------------------------------------

#例2
n = 2
def my_power():
 def power(x):
  return x ** n
 return power

n = 3
p = my_power()
print(p.__closure__)

#输出结果 None

通过例1跟例2对比,我们可以知道,例2并不是闭包

闭包经典问题

下面的程序是否是闭包?能否正确运行

def my_power():
 n = 2
 
 def power(x):
  n += 1
  return x ** n
 
 return power

p = my_power()
print(p(3))

如何让上面的程序正确运行?看看改正之后的结果

def my_power():
 n = 2
 
 def power(x):
  nonlocal n
  n += 1
  return x ** n
 
 return power

p = my_power()
print(p.__closure__)
print(p(3))
print(p(3))

看看下面的程序的运行结果

def my_power():
 n = 2
 L = []
 for i in range(1, 3):
  def power():
   return i ** n
  
  L.append(power)
 return L

f1, f2 = my_power()
print(f1())
print(f2())
print(f1.__closure__[0].cell_contents)
print(f2.__closure__[0].cell_contents)

python的函数只有在执行时,才会去找函数体里的变量的值,也就是说你连形参都不确定,你咋求知道 i为几呢?在这里,你只需要记住如果你连形参都不确定,python就只会记住最后一个i值。

装饰器及其应用

什么是装饰器模式

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

import time

start = time.time()
time.sleep(4)
end = time.time()
print(end - start)

从实际例子来看装饰器

def my_fun():
 print("这是一个函数")

my_fun()

要再打印“这是一个函数”前面在打印多一行hello world。

def my_fun():
 begin = time.time()
 time.sleep(2)
 print("这里一个函数")
 end = time.time()
 print(end-begin)

my_fun()

这个时候,如果不想修改原有的函数,咋整?

def my_fun():
 print("这是一个函数")

def my_time(func):
 begin = time.time()
 time.sleep(2)
 func()
 end = time.time()
 print(end - begin)

my_time(func)

这种方式,因为要增加功能,导致所有的业务调用方都得进行修改,此法明显不可取。

另一种方式:

def print_cost(func):
 def wrapper():
  begin = time.time()
  time.sleep(2)
  func()
  end = time.time()
  print(end - begin)
  return wrapper

@print_cost
def my_fun():
 print("这里一个函数")

第二种方式并没有修改func函数的内部实现,而是使用装饰器模式对其功能进行装饰增强。

以上就是浅谈Python 函数式编程的详细内容,更多关于Python 函数式编程的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python随机生成一个6位的验证码代码分享
Mar 24 Python
从Python的源码来解析Python下的freeblock
May 11 Python
在Python的Flask中使用WTForms表单框架的基础教程
Jun 07 Python
浅谈python jieba分词模块的基本用法
Nov 09 Python
Python3.6简单反射操作示例
Jun 14 Python
python利用openpyxl拆分多个工作表的工作簿的方法
Sep 27 Python
Python 面向对象之封装、继承、多态操作实例分析
Nov 21 Python
Python实现括号匹配方法详解
Feb 10 Python
Python列表倒序输出及其效率详解
Mar 04 Python
Python logging日志模块 配置文件方式
Jul 12 Python
Python经纬度坐标转换为距离及角度的实现
Nov 01 Python
Python数据清洗工具之Numpy的基本操作
Apr 22 Python
音频处理 windows10下python三方库librosa安装教程
Jun 20 #Python
深入浅析python 中的self和cls的区别
Jun 20 #Python
浅谈Python 参数与变量
Jun 20 #Python
python字符串的index和find的区别详解
Jun 20 #Python
Django Admin 上传文件到七牛云的示例代码
Jun 20 #Python
什么是python的函数体
Jun 19 #Python
浅谈Python中的生成器和迭代器
Jun 19 #Python
You might like
PHP并发多进程处理利器Gearman使用介绍
2016/05/16 PHP
比较完整的微信开发php代码
2016/08/02 PHP
thinkPHP5.0框架应用请求生命周期分析
2017/03/25 PHP
php自定义函数实现统计中文字符串长度的方法小结
2017/04/15 PHP
yii框架数据库关联查询操作示例
2019/10/14 PHP
LazyLoad 延迟加载(按需加载)
2010/05/31 Javascript
javascript-表格排序(降序/反序)实现介绍(附图)
2013/05/30 Javascript
一个js控制的导航菜单实例代码
2013/12/03 Javascript
Jquery实现点击按钮,连续地向textarea中添加值的实例代码
2014/03/08 Javascript
jQuery的$.proxy()应用示例介绍
2014/04/03 Javascript
jQuery select表单提交省市区城市三级联动核心代码
2014/06/09 Javascript
浅谈如何实现easyui的datebox格式化
2016/06/12 Javascript
终于实现了!精彩的jquery弹幕效果
2016/07/18 Javascript
JS实现隐藏同级元素后只显示JS文件内容的方法
2016/09/04 Javascript
微信小程序动画(Animation)的实现及执行步骤
2018/10/28 Javascript
angular6 利用 ngContentOutlet 实现组件位置交换(重排)
2018/11/02 Javascript
React 组件渲染和更新的实现代码示例
2019/02/21 Javascript
如何在微信小程序里面退出小程序的方法
2019/04/28 Javascript
基于JS实现操作成功之后自动跳转页面
2020/09/25 Javascript
[01:32]dota2拉比克至宝(222)
2018/12/20 DOTA
跟老齐学Python之有容乃大的list(1)
2014/09/14 Python
Linux下Python安装完成后使用pip命令的详细教程
2018/11/22 Python
Python数据类型之Tuple元组实例详解
2019/05/08 Python
浅谈Python访问MySQL的正确姿势
2020/01/07 Python
Python celery原理及运行流程解析
2020/06/13 Python
Python自动巡检H3C交换机实现过程解析
2020/08/14 Python
Django websocket原理及功能实现代码
2020/11/14 Python
int和Integer有什么区别
2013/05/25 面试题
工商企业管理实习自我鉴定
2013/12/04 职场文书
中学生校园广播稿
2014/01/16 职场文书
中学生班主任评语
2014/01/30 职场文书
遗产继承公证书
2014/04/09 职场文书
团党委领导干部党的群众路线教育实践活动个人对照检查材料思想汇
2014/10/05 职场文书
2014年仓管员工作总结
2014/11/18 职场文书
小学体育组工作总结2015
2015/07/21 职场文书
使用Python+OpenCV进行卡类型及16位卡号数字的OCR功能
2021/08/30 Python