当前位置: 首页 > news >正文

Python基础:函数式编程

一、概述

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

二、lambda表达式(匿名函数)

除了 函数 中介绍的 def语句,Python还提供了另外一种定义函数的方法: lambda表达式

lambda表达式的语法如下:

lambda [arguments]: expression

与def语句类似,lambda表达式创建的函数:

  • 也是可调用对象(接受0个或多个参数,返回一个值)
  • 也是一等公民(first-class)
  • 也支持嵌套定义(def中的lambda,或lambda中的lambda)

但是lambda表达式与def语句之间,也存在很多显著的差异:

差异点函数(lambda表达式)函数(def语句)
函数体只能是单行表达式(expression)可以是任意复杂的语句(statement)
函数返回值返回值就是函数体中的表达式的求值结果由函数体中的return语句指定 返回值
函数名定义后直接返回函数对象(匿名函数定义后自动为函数对象绑定函数名
函数定义位置可以在任何允许函数对象出现的位置定义(支持即时定义,即时调用)只能在允许语句出现的位置定义(先定义,后调用)
用途多用于一次性使用的简单函数适用于一切函数和类方法

以下是lambda表达式的简单示例:

# def语句
>>> def func(x, y): return x + y # 自动绑定函数名为func
... 
>>> func
<function func at 0xb76eff7c>
>>> func(1, 2) # 先定义,后调用
3# lambda表达式
>>> lambda x, y: x + y # 匿名函数(直接返回函数对象)
<function <lambda> at 0xb76ef0d4>
>>> (lambda x, y: x + y)(1, 2) # 即时定义,即时调用
3
>>> f = lambda x, y: x + y # 手动绑定函数名
>>> f(1, 2) # 也可以先定义,后调用
3
>>> 
>>> ((lambda x: (lambda y: x + y))(1))(2) # 嵌套定义的lambda(较复杂,尽量避免)
3

三、内建函数filter()、map()、reduce()

1、filter()

函数原型:filter(function, iterable)

说明:返回一个由iterable中的某些元素组成的列表,这些元素使得function返回True。若iterable为字符串(或元组),则返回字符串(或元组);否则,总是返回列表。如果function为None,则默认为恒等函数(identity function,类似 f(x) = x)。

示例:

# for循环版本
>>> res = []
>>> for x in 'a1b2c3d4e5f6':
...     if x.isalpha():
...         res.append(x)
... 
>>> res
['a', 'b', 'c', 'd', 'e', 'f']# filter版本
s = 'a1b2c3d4e5f6'
>>> filter((lambda x: x.isalpha()), s) # iterable为字符串,则返回字符串
'abcdef'
>>> filter((lambda x: x.isalpha()), tuple(s)) # iterable为元组,则返回元组
('a', 'b', 'c', 'd', 'e', 'f')
>>> filter((lambda x: x.isalpha()), list(s)) # iterable为其他迭代对象,则返回列表
['a', 'b', 'c', 'd', 'e', 'f']
>>> filter(None, list(s)) # function为None,则默认为恒等函数
['a', '1', 'b', '2', 'c', '3', 'd', '4', 'e', '5', 'f', '6']

2、map()

函数原型:map(function, iterable, ...)

说明:逐个以iterable中的元素为参数调用function,并返回结果的列表。如果存在多个iterable,则以最长的为准(其他不足的补None),逐个并行取出元素作为参数调用function(如map(function, iter1, iter2)会返回列表[function(iter1[0], iter2[0]), function(iter1[1], iter2[1]), ...])。如果function为None,则默认为恒等函数。

示例:

# for循环版本
>>> res = []
>>> for x in [1, 2, 3, 4, 5]:
...     res.append(x ** 2)
... 
>>> res
[1, 4, 9, 16, 25]# map版本
>>> map((lambda x: x ** 2), [1, 2, 3, 4, 5])
[1, 4, 9, 16, 25]
>>> map(None, [1, 2, 3, 4, 5]) # function为None,则默认为恒等函数
[1, 2, 3, 4, 5]
>>> map((lambda x, y: x + y), [1, 2, 3], [4, 5, 6]) # 存在多个iterable,则返回[1+4, 2+5, 3+6]
[5, 7, 9]
>>> map(None, [1, 2, 3], [4, 5]) # 以最长的iterable为准,其他不足的补None
[(1, 4), (2, 5), (3, None)]

3、reduce()

函数原型:reduce(function, iterable[, initializer])

说明:以累加方式逐个取出iterable中的元素作为参数调用(具有双参数的)function,从而最终将iterable简化为一个值(如reduce(function, [1, 2, 3])会返回function(function(1, 2), 3))。如果存在initializer,则在累加调用中,以它作为初始的第一个参数。function必须是可调用对象(不能为None)。

示例:

# for循环版本
>>> total = 0
>>> for x in [1, 2, 3, 4, 5]:
...     total += x
... 
>>> total
15# reduce版本
>>> reduce((lambda x, y: x + y), [1, 2, 3, 4, 5]) # 相当于((((1+2)+3)+4)+5)
15
>>> reduce((lambda x, y: x + y), [1, 2, 3, 4, 5], 10) # 带有initializer的reduce,相当于(((((10+1)+2)+3)+4)+5)
25
>>> sum([1, 2, 3, 4, 5], 10) # 等效于上面的reduce
25

四、闭包

闭包(closure)是一个内嵌函数,它能够记住其 外围作用域 中的所有名字,即使这个作用域 看起来 已经不在外围。

在以下示例中,内嵌函数action就是一个闭包:

>>> def maker(N):
...     def action(x):
...         return x * N
...     return action
... 
>>> mul10 = maker(10)
>>> mul10(3)
30
>>> mul10(5)
50

尽管函数调用mul10 = maker(10)已经返回并退出了,但后续的mul10却能够记住整数10,从而计算入参的10倍数。

实际上,外围作用域(如函数maker对应的代码范围)中的所有名字(如参数N)都作为环境信息被绑定到了action函数上,因此每次调用action时都可以访问这些环境信息。特别地,可以通过特殊属性func_closure来获取一个函数的自由变量绑定:

>>> def maker(N):
...     def action(x):
...         return x * N
...     print(action.func_closure) # 打印出action函数的func_closure属性值
...     return action
... 
>>> N = 10
>>> print('int N: id = %#0x, val = %d' % (id(N), N)) # N的值为10(整数10的地址是0x8e82044)
int N: id = 0x8e82044, val = 10
>>> mul10 = maker(N) # action.func_closure中含有整数10(即自由变量N)
(<cell at 0x90e96bc: int object at 0x8e82044>,)

闭包的这种 能够记住环境状态 的特性非常有用,Python中有一些其他特性就是借助闭包来实现的,比如 装饰器。

五、偏函数应用

1、基本用法

偏函数应用(Partial Function Application)是一种简化函数调用的方式,主要表现为对函数的部分参数进行固化。

Python中的偏函数应用是借助 functools.partial 来完成的。例如有一个专用于生成文章标题的函数title:

>>> def title(topic, part):
...     return topic + u':' + part
...

如果要为python基础系列的多篇文章生成标题,可以有以下两种方式:

# 普通版本
>>> print title(u'Python基础', u'开篇')
Python基础:开篇
>>> print title(u'Python基础', u'函数')
Python基础:函数
>>> print title(u'Python基础', u'函数式编程')
Python基础:函数式编程# 偏函数版本
>>> from functools import partial
>>> pybasic_title = partial(title, u'Python基础')
>>> print pybasic_title(u'开篇')
Python基础:开篇
>>> print pybasic_title(u'函数')
Python基础:函数
>>> print pybasic_title(u'函数式编程')
Python基础:函数式编程

从上面的示例可以看出,如果在编码过程中遇到了“多次用相同的参数调用一个函数”的场景,就可以考虑使用偏函数来固化这些相同的参数,进而简化函数调用。

2、等效实现

1)默认参数

在上述示例中,如果将函数title的定义改为def title(part, topic=u'Python基础')也可以达到相同的效果。但是这种方式的不足之处也很明显:

  • 需要修改已有函数title的定义
  • 默认参数只能有一个固定值,定义后即不能更改

相比之下,偏函数具有很好的灵活性:既不用修改已有函数的定义,又可以为函数的参数固化不同的值。

2)lambda表达式

使用 lambda表达式 也可以实现类似偏函数的功能,并且与默认参数不同的是,可以针对不同的参数值定义不同的lambda表达式(因为lambda表达式通常是一次性使用的)。例如上述示例中的pybasic_title也可以实现为:

>>> pybasic_title = (lambda part: u'Python基础:' + part)
>>> print pybasic_title(u'开篇')
Python基础:开篇
>>> print pybasic_title(u'函数')
Python基础:函数
>>> print pybasic_title(u'函数式编程')
Python基础:函数式编程

但是,由于lambda表达式本身的限制(参考 『lambda表达式』 一节),在具有复杂函数的场景中,还得使用偏函数。

3)闭包

最后,使用 闭包 同样可以等效地实现偏函数的功能,并且与lambda表达式不同的是,它没有任何限制场景。还是上面的例子:

>>> def title(topic):
...     def topic_title(part):
...         return topic + u':' + part
...     return topic_title
... 
>>> pybasic_title = title(u'Python基础')
>>> print pybasic_title(u'开篇')
Python基础:开篇
>>> print pybasic_title(u'函数')
Python基础:函数
>>> print pybasic_title(u'函数式编程')
Python基础:函数式编程

可以看出,这个闭包版本的唯一缺点是它需要对函数title进行重新定义(与默认参数的情况有些类似)。

总而言之,如果需要对 已有函数 进行参数固化,偏函数是最佳选择。

六、列表解析

这里主要强调两点:

  • 列表解析可以用来代替上面提到的一些函数式编程方法
  • 列表解析还有一个生成器版本的近亲:生成器表达式

1、用列表解析代替filter()和map()

1)filter()

列表解析可以完全代替filter():

  • function不为None时:[item for item in iterable if function(item)]等价于filter(function, iterable)
  • function等于None时:[item for item in iterable if item]等价于filter(None, iterable)

2)map()

在以下情况中,列表解析可以代替map():

  • 只有一个iterable时
    • function不为None:[function(item) for item in iterable]等价于map(function, iterable)
    • function等于None:[item for item in iterable]等价于map(None, iterable)
  • 多个iterable长度相同时
    • function不为None:[function(*args) for args in zip(iter1, iter2, ...)]等价于map(function, iter1, iter2, ...)
    • function等于None:zip(iter1, iter2, ...)等价于map(None, iter1, iter2, ...)

如果多个iterable具有不同的长度,那么列表解析就无法代替map()了。

2、生成器表达式

生成器表达式(Generator Expressions)与列表解析在语法和功能方面都非常相似。二者的根本差异是:生成器表达式返回一个 生成器,而列表解析返回一个列表。如下所示:

差异点生成器表达式列表解析
表示方法(expr for item in iterable if cond_expr)[expr for item in iterable if cond_expr]
返回值一个生成器一个列表

与列表解析相比,生成器表达式具有 延迟计算(lazy evaluation)的特点,因此在使用内存上更有效。

相关文章:

Python基础:函数式编程

一、概述 Python是一门多范式的编程语言&#xff0c;它同时支持过程式、面向对象和函数式的编程范式。因此&#xff0c;在Python中提供了很多符合 函数式编程 风格的特性和工具。 二、lambda表达式&#xff08;匿名函数&#xff09; 除了 函数 中介绍的 def语句&#xff0c;P…...

【YBT2023寒假Day14 C】字符串题(SAM)(树链剖分)(线段树)

字符串题 题目链接&#xff1a;YBT2023寒假Day14 C 题目大意 对于一个字符串 S 定义 F(S) 是 fail 树上除了 0 点其它点的深度和。 G(S) 是 S 每个子串 S’ 的 F(S’) 之和。 然后一个空串&#xff0c;每次在后面加一个字符&#xff0c;要你维护这个串的 G 值。 思路 考虑…...

Tailwind CSS 在Vue中的使用

什么是Tailwind CSS&#xff1f; Tailwind CSS 是一个功能类优先的 CSS 框架&#xff0c;它集成了诸如 flex, pt-4, text-center 和 rotate-90 这样的的类&#xff0c;支持 hover 和 focus 样式&#xff0c;它们能直接在脚本标记语言中组合起来&#xff0c;构建出任何设计。 …...

三层楼100人办公网络如何规划设计实施(实战案例)

如何设计组网 1.采用防火墙+三层交换机+二层POE交换机+AP的方案 2.三层交换机作为网络的核心,提供网络的配置、划分和各个VLAN间的数据交换,而每个VLAN由二层交换机组建 3.网络主干设备的选型,建议网络主干设备或核心层设备选择具备第3层交换功能的高性能主干交换机。 4…...

Redis:实现全局唯一ID

Redis&#xff1a;实现全局唯一ID一. 概述二. 实现&#xff08;1&#xff09;获取初始时间戳&#xff08;2&#xff09;生成全局ID三. 测试为什么可以实现全局唯一&#xff1f;其他唯一ID策略补充&#xff1a;countDownLatch一. 概述 全局ID生成器&#xff1a;是一种在【分布式…...

webpack打包基本原理——实现webpack打包核心功能

webpack打包的基本原理 核心功能就是把我们写的模块化代码转换成浏览器能够识别运行的代码&#xff0c;话不多说我们一起来了解它 首先我们建一个空项目用 npm init -y 创建一个初始化的&#xff0c;在跟目录下创建src文件夹&#xff0c;src下创建index.js&#xff0c;add.js…...

git的使用(终端输入指令) 上

git目录前言1.创建仓库2.创建文件和修改数据状态分区![分区](https://img-blog.csdnimg.cn/d124dec6b2b14769ad20b75490f29cae.png)3 .删除、撤销重置 、和比较前言 今天带大家手把手敲一遍 git 流程&#xff1a; 安装一下git&#xff08;详细观看我之前发的git文档&#xff0…...

react定义css样式,使用less,css模块化

引入外部 css文件 import ./index.css此时引入的样式是全局样式 使用less 安装 npm i style-loader css-loader sass-loader node-sass -D生成config文件夹 npm run eject配置 以上代码运行完&#xff0c;会在根目录生成config文件夹 进入 config > webpack.config.js 查找…...

基于JavaWeb的学生管理系统

文章目录 项目介绍主要功能截图:登录用户信息管理院系信息管理班级信息管理新增学生课程管理成绩管理部分代码展示设计总结项目获取方式🍅 作者主页:Java韩立 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系�…...

win11右键新建菜单添加选项

需要操作 2 处注册表&#xff0c; 以下以在右键新建菜单中添加 .html 为例 在主键 HKEY_CLASSES_ROOT 中&#xff0c;搜索 .html 找到后 &#xff0c;右键点击它&#xff0c;选 新建 ->项&#xff0c; 在这里插入图片描述 项目名字是&#xff1a;ShellNew 新建后&#x…...

leetcode Day5(卡线复试,放弃版)

Day5 最后一个单词长度&#xff08;要求最后一个&#xff0c;可以反向计数&#xff09; int lens.length()-1; while(s.charAt(len)){len--;//最后是一个空格&#xff0c;就是无字符时 } int wordlen0;//记录字符长度 /*charAt() 方法用于返回指定索引处的字符。索引范围为从 0…...

cmake 入门二 库的编译,安装与使用

工程描述 &#xff11;&#xff0c;建立一个静态库和动态库&#xff0c;提供HelloFunc 函数供其他程序编程使用&#xff0c;HelloFunc 向终端输出Hello World字符串。 &#xff12;&#xff0c;安装头文件与共享库。 1 库的工程结构 1.1 工程目录下的CMakeLists.txt PROJECT…...

Python中实现将内容进行base64编码与解码

一、需求说明需要使用Python实现将内容转为base64编码&#xff0c;解码&#xff0c;方便后续的数据操作。二、base64简介Base64是一种二进制到文本的编码方式【是一种基于 64 个可打印字符来表示二进制数据的表示方法&#xff08;由于 2^664&#xff0c;所以每 6 个比特为一个单…...

集合TreeSet的使用-java

TreeSet的特点&#xff1a;可排序、不重复、无索引。可排序&#xff1a;按照元素的大小默认升序排序&#xff1b;底层是基于红黑树的数据结构实现排序的&#xff0c;增删改查性能都较好。对于数值、字符串类型的&#xff08;Integer 、Double、String&#xff09;TreeSet可以排…...

Mybatis-plus 分页集成以及基本使用总结 入门和案例 注解连表查询分页案例等

简介 Mybaits-plus 是mybits 的升级版&#xff0c;从mybaits 升级到mybaits-plus 可以实现平滑升级 Mybaits-plus 本身提供了大量的基本查询方法以及强大的 Wrapper(包装) 类 用于查询的 QueryWrapper 以及 更新的 UpdateWrapper &#xff0c;使用Wrapper 基本已经可以构建大…...

5个设计师常用素材库

推荐5个设计素材网站&#xff0c;免费下载&#xff01; 1、菜鸟图库 菜鸟图库-免费设计素材下载 菜鸟图库是一个素材量非常丰富的网站&#xff0c;该网站聚合了平面、UI、淘宝电商、高清背景图、图片、插画等高质量素材。平面设计模板非常多&#xff0c;很多都能免费下载&…...

PHP/7.2.11 缺少 apache2/logs/httpd.pid 文件

启动服务时&#xff1a;systemctl restart httpd.service&#xff0c;报错&#xff1a;● httpd.service - httpd serviceLoaded: loaded (/etc/systemd/system/httpd.service; enabled; vendor preset: disabled)Active: failed (Result: exit-code) since 五 2023-02-24 16:1…...

【centos7下部署mongodb】

一.安装环境 CentOS7MongoDB4.0.13正式版。 二.下载MongoDB 1.1 官网下载地址&#xff1a;https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.13.tgz 1.2 将压缩包通过xftp上传到服务器/opt目录&#xff0c;然后解压、改名 三. 配置环境变量及配置文件 3.1配置系…...

pycharm首次使用爬虫框架scrapy遇到的问题和解决方法(二)

在首次使用scrapy框架的过程中,一直是对着别人的框架步骤撸代码的。然而,撸着撸着发现好像别人的也用不了。后面就只能自己找踏坑了。 问题报错: 1,IndexError: list index out of range 2,pymysql.err.ProgrammingError: (1064, "You have an error in your SQL s…...

pyflink学习笔记(二):table_apisql

Joins Inner Join 官网说明&#xff1a;和 SQL 的 JOIN 子句类似。关联两张表。两张表必须有不同的字段名&#xff0c;并且必须通过 join 算子或者使用 where 或 filter 算子定义至少一个 join 等式连接谓词。先创建2个表&#xff0c;两个表的字段是相同的&#xff0c;我想验证…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点&#xff1a;传参类型必须是类对象 一、BigInteger 1. 作用&#xff1a;适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...

Monorepo架构: Nx Cloud 扩展能力与缓存加速

借助 Nx Cloud 实现项目协同与加速构建 1 &#xff09; 缓存工作原理分析 在了解了本地缓存和远程缓存之后&#xff0c;我们来探究缓存是如何工作的。以计算文件的哈希串为例&#xff0c;若后续运行任务时文件哈希串未变&#xff0c;系统会直接使用对应的输出和制品文件。 2 …...

Qt的学习(二)

1. 创建Hello Word 两种方式&#xff0c;实现helloworld&#xff1a; 1.通过图形化的方式&#xff0c;在界面上创建出一个控件&#xff0c;显示helloworld 2.通过纯代码的方式&#xff0c;通过编写代码&#xff0c;在界面上创建控件&#xff0c; 显示hello world&#xff1b; …...

npm安装electron下载太慢,导致报错

npm安装electron下载太慢&#xff0c;导致报错 背景 想学习electron框架做个桌面应用&#xff0c;卡在了安装依赖&#xff08;无语了&#xff09;。。。一开始以为node版本或者npm版本太低问题&#xff0c;调整版本后还是报错。偶尔执行install命令后&#xff0c;可以开始下载…...