浅谈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抓取京东商城手机列表url实例代码
Dec 18 Python
python获取标准北京时间的方法
Mar 24 Python
深入理解Python中字典的键的使用
Aug 19 Python
Python删除Java源文件中全部注释的实现方法
Aug 30 Python
一道python走迷宫算法题
Jan 22 Python
python实现识别手写数字 python图像识别算法
Mar 23 Python
python 按照固定长度分割字符串的方法小结
Apr 30 Python
Python装饰器的执行过程实例分析
Jun 04 Python
解决python写入mysql中datetime类型遇到的问题
Jun 21 Python
tensorboard实现同时显示训练曲线和测试曲线
Jan 21 Python
selenium+python配置chrome浏览器的选项的实现
Mar 18 Python
Python使用monkey.patch_all()解决协程阻塞问题
Apr 15 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与javascript对多项选择的处理
2006/10/09 PHP
php获取excel文件数据
2017/04/21 PHP
PHP编程实现脚本异步执行的方法
2017/08/09 PHP
php实现的生成迷宫与迷宫寻址算法完整实例
2017/11/06 PHP
Laravel find in set排序实例
2019/10/09 PHP
extjs fckeditor集成代码
2009/05/10 Javascript
jQuery的实现原理的模拟代码 -1 核心部分
2010/08/01 Javascript
基于jQuery的合并表格中相同文本的相邻单元格的代码
2011/04/06 Javascript
js实现屏蔽默认快捷键调用自定义事件示例
2013/06/18 Javascript
详解自定义ajax支持跨域组件封装
2018/02/08 Javascript
jQuery实现的回车触发按钮事件功能示例
2018/03/25 jQuery
移动端H5页面返回并刷新页面(BFcache)的方法
2018/11/06 Javascript
vue中引入mxGraph的步骤详解
2019/05/17 Javascript
NodeJS实现一个聊天室功能
2019/11/25 NodeJs
javascript的hashCode函数实现代码小结
2020/08/11 Javascript
nuxt.js服务端渲染中axios和proxy代理的配置操作
2020/11/06 Javascript
[51:17]VGJ.T vs Mineski 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
python支持断点续传的多线程下载示例
2014/01/16 Python
在Linux命令行终端中使用python的简单方法(推荐)
2017/01/23 Python
python中字符串的操作方法大全
2018/06/03 Python
Python lxml解析HTML并用xpath获取元素的方法
2019/01/02 Python
Django 过滤器汇总及自定义过滤器使用详解
2019/07/19 Python
ipad上运行python的方法步骤
2019/10/12 Python
Python 判断时间是否在时间区间内的实例
2020/05/16 Python
python爬虫构建代理ip池抓取数据库的示例代码
2020/09/22 Python
GAP美国官网:美国休闲时尚品牌
2016/08/26 全球购物
加拿大租车网站:Enterprise Rent-A-Car
2018/07/26 全球购物
PHP面试题-$message和$$message的区别
2015/12/08 面试题
创建索引时需要注意的事项
2013/05/13 面试题
营销总经理的岗位职责
2013/12/15 职场文书
社会实践评语
2014/04/28 职场文书
六查六看六改心得体会
2014/10/14 职场文书
四风问题专项整治工作情况报告
2014/10/28 职场文书
详解php中流行的rpc框架
2021/05/29 PHP
quickjs 封装 JavaScript 沙箱详情
2021/11/02 Javascript
golang实现浏览器导出excel文件功能
2022/03/25 Golang