浅谈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 相关文章推荐
分享15个最受欢迎的Python开源框架
Jul 13 Python
小白入门篇使用Python搭建点击率预估模型
Oct 12 Python
python pandas实现excel转为html格式的方法
Oct 23 Python
Python使用到第三方库PyMuPDF图片与pdf相互转换
May 03 Python
Python实现的插入排序,冒泡排序,快速排序,选择排序算法示例
May 04 Python
Python实现的统计文章单词次数功能示例
Jul 08 Python
Python实现决策树并且使用Graphviz可视化的例子
Aug 09 Python
Python3爬虫里关于识别微博宫格验证码的知识点详解
Jul 30 Python
Python字符串及文本模式方法详解
Sep 10 Python
如何基于pandas读取csv后合并两个股票
Sep 25 Python
python使用正则表达式匹配txt特定字符串(有换行)
Dec 09 Python
Python下opencv使用hough变换检测直线与圆
Jun 18 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
深入分析使用mysql_fetch_object()以对象的形式返回查询结果
2013/06/05 PHP
Yii框架结合sphinx,Ajax实现搜索分页功能示例
2016/10/18 PHP
jQuery插件 tabBox实现代码
2010/02/09 Javascript
jquery validate.js表单验证的基本用法入门
2010/05/13 Javascript
jQuery 通过事件委派一次绑定多种事件,以减少事件冗余
2010/06/30 Javascript
jQuery获取css z-index在各种浏览器中的返回值
2010/09/15 Javascript
在vs2010中调试javascript代码方法
2011/02/11 Javascript
解决用jquery load加载页面到div时,不执行页面js的问题
2014/02/22 Javascript
jquery 判断滚动条到达了底部和顶端的方法
2014/04/02 Javascript
$(document).ready(function() {})不执行初始化脚本
2014/06/19 Javascript
JS实现自适应高度表单文本框的方法
2015/02/25 Javascript
js实现图片淡入淡出切换简易效果
2016/08/22 Javascript
angular仿支付宝密码框输入效果
2017/03/25 Javascript
js中less常用的方法小结
2017/08/09 Javascript
详解Angular路由之路由守卫
2018/05/10 Javascript
vue项目每30秒刷新1次接口的实现方法
2018/12/04 Javascript
javascript设计模式 ? 单例模式原理与应用实例分析
2020/04/09 Javascript
JS数据类型判断的几种常用方法
2020/07/07 Javascript
解决nuxt 自定义全局方法,全局属性,全局变量的问题
2020/11/05 Javascript
Python聚类算法之基本K均值实例详解
2015/11/20 Python
python中的编码知识整理汇总
2016/01/26 Python
Python使用email模块对邮件进行编码和解码的实例教程
2016/07/01 Python
使用PyInstaller将Python程序文件转换为可执行程序文件
2016/07/08 Python
python利用matplotlib库绘制饼图的方法示例
2016/12/18 Python
基于python进行桶排序与基数排序的总结
2018/05/29 Python
详解pyppeteer(python版puppeteer)基本使用
2019/06/12 Python
Python Django 简单分页的实现代码解析
2019/08/21 Python
python getpass模块用法及实例详解
2019/10/07 Python
解决python replace函数替换无效问题
2020/01/18 Python
Lookfantastic美国/加拿大:英国知名美妆购物网站
2019/03/27 全球购物
生产车间实习自我鉴定
2013/09/23 职场文书
软件工程专业推荐信
2013/10/28 职场文书
应聘面试自我评价
2014/01/24 职场文书
超市采购员岗位职责
2015/04/07 职场文书
《秋天的图画》教学反思
2016/02/19 职场文书
Vue的过滤器你真了解吗
2022/02/24 Vue.js