本节内容

一、函数式编程

二、高阶函数

  1、变量可以指向函数

  2、函数名也是变量

  3、传入函数

三、返回函数

  1、函数作为返回值

  2、闭包特性

一、函数式编程

函数是Python内建支持的一种封装,我们通过把大段代码拆成函数,通过一层一层的函数调用,就可以把复杂任务分解成简单的任务,

这种分解可以称之为面向过程的程序设计。函数就是面向过程的程序设计的基本单元

我们首先要搞明白计算机(Computer)和计算(Compute)的概念。

在计算机的层次上,CPU执行的是加减乘除的指令代码,以及各种条件判断和跳转指令,所以,汇编语言是最贴近计算机的语言。

而计算则指数学意义上的计算,越是抽象的计算,离计算机硬件越远。

对应到编程语言,就是越低级的语言,越贴近计算机,抽象程度低,执行效率高,比如C语言;

越高级的语言,越贴近计算,抽象程度高,执行效率低,比如Lisp语言。

函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,

因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用

而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的

函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数

Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

二、高阶函数

高阶函数 Higher-order function

1、变量可以指向函数

print(abs(-10))  # 调用绝对值函数
print(abs) # 函数本身 x = abs(-10) # 函数返回值 10 赋给变量 x, f = abs # 函数本身赋值给变量 f ,即变量可以指向函数
print(f(-10)) # 输出结果为 10 # 说明变量 f 已经指向了abs函数本身。直接调用abs()函数和调用变量f()完全相同

2、函数名也是变量

函数名其实就是指向函数的变量!对于abs()这个函数,完全可以把函数名abs看成变量,它指向一个可以计算绝对值的函数

abs = 10

print(abs)       # 输出结果  10
print(abs(-10)) # 错误信息 TypeError: 'int' object is not callable

把abs指向10后,就无法通过abs(-10)调用该函数了!因为abs这个变量已经不指向求绝对值函数而是指向一个整数10!

3、传入函数

既然变量可以指向函数,函数的参数能就收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数

def add(x, y, f):
return f(x) + f(y) add_sum = add(-10, 10, abs) # x=-10 y=10 f=abs
print(add_sum)

编写高阶函数,就是让函数的参数能够接收别的函数

三、返回函数

1、函数作为返回值

高阶函数除了可以接收函数作为参数外,还可以把函数作为结果值返回。

实现一个可变参数的求和。通常情况下,求和的参数是这样定义的:

def calc_sum(*args):
ax = 0
for n in args:
ax += n
return ax

但是,如果不立刻求和,而是在后面的代码中,根据需要再计算,所以可以不返回求和的结果,而是返回求和的函数:

def lazy_sum(*args):
def inner_sum():
ax = 0
for n in args:
ax += n
return ax
return inner_sum # 定义时,返回相应函数 f1 = lazy_sum(1, 3, 5, 7, 9) # 调用函数lazy_sum,返回值为函数inner_sum
f2 = lazy_sum(1, 3, 5, 7, 9) # 调用函数lazy_sum,返回值为函数inner_sum print(f1) # <function lazy_sum.<locals>.inner_sum at 0x000000B2C801C510>,返回值为函数 inner_sum
print(f1 == f2) # False, 说明 f1和f2是独立的 print(f1()) # 调用函数f1,返回值为求和结果
print(f2()) # 调用函数f2,返回值为求和结果

在这个例子中,我们在函数lazy_sum中又定义了函数calc_sum,并且,内部函数calc_sum可以引用外部函数lazy_sum的参数和局部变量,

当lazy_sum返回函数calc_sum时,相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。

请再注意一点,当我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数。

2、闭包特性

注意到返回的函数在其定义内部引用了局部变量args,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用

闭包用起来简单,实现起来可不容易。

另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了f()才执行。我们来看一个例子:

def count():
fs = []
for i in range(1, 4):
def func():
return i*i
fs.append(func) # 把函数名func,添加到列表fs
return fs # 返回值为列表 print(count()) # 列表,其中元素为函数func
f4, f5, f6 = count() # 把列表元素依次赋给f4,f5,f6
print("f4(): ", f4()) # 调用函数func(),返回 i*i,结果为9
print("f5(): ", f4()) # 调用函数func(),返回 i*i,结果为9
print("f4(): ", f4()) # 调用函数func(),返回 i*i,结果为9

在上面的例子中,每次循环,都创建了一个新的函数,然后,把创建的个函数都返回了,实际的返回结果都为。

原因在于返回的函数引用了变量i,但它并非立刻执行。等到个函数都返回时,它们所引用的变量i已经变成了,因此最终结果都为

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量

Python自动化开发 - 函数式编程的更多相关文章

  1. Python自动化开发 - 网络编程

    本节内容 1.客户端/服务器架构 2.OSI七层 3.socket层 4.socket是什么 5.套接字发展史及分类 6.套接字工作流程 一.客户端/服务器架构 即Client/Server架构,包括 ...

  2. Python Decorator 和函数式编程

    看到一篇翻译不错的文章,原文链接: Python Decorator 和函数式编程

  3. Python基础:函数式编程

    一.概述 Python是一门多范式的编程语言,它同时支持过程式.面向对象和函数式的编程范式.因此,在Python中提供了很多符合 函数式编程 风格的特性和工具. 以下是对 Python中的函数式编程 ...

  4. Python进阶:函数式编程实例(附代码)

    Python进阶:函数式编程实例(附代码) 上篇文章"几个小例子告诉你, 一行Python代码能干哪些事 -- 知乎专栏"中用到了一些列表解析.生成器.map.filter.lam ...

  5. 可爱的 Python : Python中的函数式编程,第三部分

    英文原文:Charming Python: Functional programming in Python, Part 3,翻译:开源中国 摘要:  作者David Mertz在其文章<可爱的 ...

  6. Python进阶之函数式编程(把函数作为参数)

    什么是函数式编程? 什么是函数式编程? 函数:function 函数式:functional,一种编程范式 函数式编程是一种抽象计算的编程模式 函数≠函数式,比如:计算≠计算机 在计算机当中,计算机硬 ...

  7. python自动化开发学习 进程, 线程, 协程

    python自动化开发学习 进程, 线程, 协程   前言 在过去单核CPU也可以执行多任务,操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换任务2,任务2执行0.01秒,在切换到任务3,这 ...

  8. python自动化开发学习 I/O多路复用

    python自动化开发学习 I/O多路复用   一. 简介 socketserver在内部是由I/O多路复用,多线程和多进程,实现了并发通信.IO多路复用的系统消耗很小. IO多路复用底层就是监听so ...

  9. Python之面向对象函数式编程

    Python之面向对象函数式编程 函数式编程的根本就是用 def 去模拟数学式的编程逻辑. 类似与 y = 2*x + 1 ,当x = 3 时,函数的结果y就得7. def test(x): retu ...

随机推荐

  1. div同时使用两个class

    <p class="con hide">...</p> 1:使用空格分割 2:这个段落将同时应用这两个 class 制定的规则 3:如果二者有重叠,后者覆盖 ...

  2. [SoapUI] 从Map里面不想要的键值对

    def keysToRemoveForBoss = ["RequestIdBmk", "RequestIdTest"] def extraInfoMapForB ...

  3. Netty 源码 ChannelHandler(四)编解码技术

    Netty 源码 ChannelHandler(四)编解码技术 Netty 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) 一.拆包与粘 ...

  4. 设计师别浪费时间啦,快来试试这款Sketch标注插件吧

    随着移动互联网的快速发展,用户的需求也在不断地增大,这对产品经理还有设计师的考验是越来越大.市场环境的变化让我们深信为快不破,但是一个产品的产出需要各个环节的紧密配合,但往往在产品输出过程中,由于分工 ...

  5. sqlserver 数据迁移

    转载地址: 1.https://blog.csdn.net/yh_zeng2/article/details/72901892 2.https://www.cnblogs.com/jpfss/p/91 ...

  6. Git使用基础篇(zz)

    Git使用基础篇 您的评价:          收藏该经验       Git是一个分布式的版本控制工具,本篇文章从介绍Git开始,重点在于介绍Git的基本命令和使用技巧,让你尝试使用Git的同时,体 ...

  7. SparkStreaming--reduceByKeyAndWindow

    1.reduceByKeyAndWindow(_+_,Seconds(3), Seconds(2))     可以看到我们定义的window窗口大小Seconds(3s) ,是指每2s滑动时,需要统计 ...

  8. mybatis 接口绑定 和 动态SQL

    一.MyBatis 接口绑定方案及多参数传递 1.作用:实现创建一个接口后把mapper.xml由mybatis生成接口的实现类,通过调用接口对象就可以获取mapper.xml中编写的sql 2.后面 ...

  9. zookeeper 单机集成部署

    概述 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务,配置维护和命名服务等,是很多分布式的基础设置,比如dubbo,k ...

  10. python 基础_ 数组的 增删改查3

    数组是运用在多个数据存在一个变量中的,而在调用的时候可以调用所需要的数组. 创建数组 a = ['a','b','c','d','f'] #创建一个数组a其中有5个元素分别是abcdf 1.查询.所谓 ...