目录
头等函数
把函数作为对象
把对象作为函数
数据结构内的函数
把函数作为参数和返回值
嵌套函数
单表达式函数(Lambda 表达式)
Map、Filter 和 Reduce
Map
Filter
Reduce
首页 后端开发 Python教程 一文详尽 Python 函数式编程技术

一文详尽 Python 函数式编程技术

Apr 13, 2023 pm 03:16 PM
python 编程 技术

本文对 Python 中的函数式编程技术进行了简单的入门介绍。

图片

头等函数

在 Python 中,函数是「头等公民」(first-class)。也就是说,函数与其他数据类型(如 int)处于平等地位。

因而,我们可以将函数赋值给变量,也可以将其作为参数传入其他函数,将它们存储在其他数据结构(如 dicts)中,并将它们作为其他函数的返回值。

把函数作为对象

由于其他数据类型(如 string、list 和 int)都是对象,那么函数也是 Python 中的对象。我们来看示例函数 foo,它将自己的名称打印出来:

def foo():
 print("foo")
登录后复制

由于函数是对象,因此我们可以将函数 foo 赋值给任意变量,然后调用该变量。例如,我们可以将函数赋值给变量 bar:

bar = foo
bar()
#will print "foo" to the console
登录后复制

语句 bar = foo 将函数 foo 引用的对象赋值给变量 bar。

把对象作为函数

当对象可调用时(callable),它们与函数一样,如 object()。这是通过 call 方法实现的。

示例如下:

class Greeter:
 def __init__(self, greeting):
self.greeting = greeting
 def __call__(self, name):
return self.greeting + " " + name
登录后复制

每一次配置 Greeter 类的对象时,我们都会创建一个新的对象,即打招呼时可以喊的新名字。如下所示:

morning = Greeter("good morning") #creates the callable object
morning("john") # calling the object
#prints "good morning john" to the console
登录后复制

我们可以调用 morning 对象的原因在于,我们已经在类定义中使用了 call 方法。为了检查对象是否可调用,我们使用内置函数 callable:

callable(morning) #true
callable(145) #false. int is not callable.
登录后复制

数据结构内的函数

函数和其他对象一样,可以存储在数据结构内部。例如,我们可以创建 int to func 的字典。当 int 是待执行步骤的简写时,这就会派上用场。

# store in dictionary
mapping = {
 0 : foo,
 1 : bar
}
x = input() #get integer value from user
mapping[x]() #call the func returned by dictionary access
登录后复制

类似地,函数也可以存储在多种其他数据结构中。

把函数作为参数和返回值

函数还可以作为其他函数的参数和返回值。接受函数作为输入或返回函数的函数叫做高阶函数,它是函数式编程的重要组成部分。

高阶函数具备强大的能力。就像《Eloquent JavaScript》中解释的那样:

「高阶函数允许我们对动作执行抽象,而不只是抽象数值。」

我们来看一个例子。假设我们想对一个项目列表(list of items)执行迭代,并将其顺序打印出来。我们可以轻松构建一个 iterate 函数:

def iterate(list_of_items):
for item in list_of_items:
print(item)
登录后复制

看起来很酷吧,但这只不过是一级抽象而已。如果我们想在对列表执行迭代时进行打印以外的其他操作要怎么做呢?

这就是高阶函数存在的意义。我们可以创建函数 iterate_custom,待执行迭代的列表和要对每个项应用的函数都是 iterate_custom 函数的输入:

def iterate_custom(list_of_items, custom_func):
 for item in list_of_items:
custom_func(item)
登录后复制

这看起来微不足道,但其实非常强大。

我们已经把抽象的级别提高了一层,使代码具备更强的可重用性。现在,我们不仅可以在打印列表时调用该函数,还可以对涉及序列迭代的列表执行任意操作。

函数还能被返回,从而使事情变得更加简单。就像我们在 dict 中存储函数一样,我们还可以将函数作为控制语句,来决定适合的函数。例如:

def add(x, y):
return x + y
def sub(x, y):
return x - y
def mult(x, y):
return x * y
def calculator(opcode):
if opcode == 1:
 return add
elif opcode == 2:
 return sub
else:
 return mult 
my_calc = calculator(2) #my calc is a subtractor
my_calc(5, 4) #returns 5 - 4 = 1 
my_calc = calculator(9) #my calc is now a multiplier
my_calc(5, 4) #returns 5 x 4 = 20.
登录后复制

嵌套函数

函数还可以在其他函数内部,这就是「内部函数」。内部函数在创建辅助函数时非常有用,辅助函数即作为子模块来支持主函数的小型可重用函数。

在问题需要特定函数定义(参数类型或顺序)时,我们可以使用辅助函数。这种不遵循传统做法的操作使得解决问题变得更加简单,示例参见:

http://www-inst.eecs.berkeley.edu/~cs61a/sp12/lectures/lect4-2x3.pdf。

假设你想定义一个斐波那契函数 fib(n),该函数只有一个参数 n,我们必须返回第 n 个斐波那契数。

定义此类函数的一种可行方式是:使用辅助函数来追踪斐波那契数列的前两个项(因为斐波那契数是前两个数之和)。

def fib(n):
def fib_helper(fk1, fk, k):
if n == k:
 return fk
else:
 return fib_helper(fk, fk1+fk, k+1)
if n <= 1:
 return n
else:
 return fib_helper(0, 1, 1)
登录后复制

将该计算从函数主体移到函数参数,这具备非常强大的力量。因为它减少了递归方法中可能出现的冗余计算。

单表达式函数(Lambda 表达式)

如果我们想在未给函数命名之前写一个函数要怎么做?如果我们想写一个简短的单行函数(如上述示例中的函数 foo 或 mult)要怎么做?

我们可以在 Python 中使用 lambda 关键字来定义此类函数。示例如下:

mult = lambda x, y: x * y
mult(1, 2) #returns 2
登录后复制

该 mult 函数的行为与使用传统 def 关键字定义函数的行为相同。

注意:lambda 函数必须为单行,且不能包含程序员写的返回语句。

事实上,它们通常具备隐式的返回语句(在上面的示例中,函数想表达 return x * y,不过我们省略了 lambda 函数中的显式返回语句)。

lambda 函数更加强大和精准,因为我们还可以构建匿名函数(即没有名称的函数):

(lambda x, y: x * y)(9, 10) #returns 90
登录后复制

当我们只需要一次性使用某函数时,这种方法非常方便。例如,当我们想填充字典时:

import collections
pre_fill = collections.defaultdict(lambda: (0, 0))
#all dictionary keys and values are set to 0
登录后复制

接下来我们来看 Map、Filter 和 Reduce,以更多地了解 lambda。

Map、Filter 和 Reduce

Map

map 函数基于指定过程(函数)将输入集转换为另一个集合。这类似于上文提到的 iterate_custom 函数。例如:

def multiply_by_four(x):
return x * 4
scores = [3, 6, 8, 3, 5, 7]
modified_scores = list(map(multiply_by_four, scores))
#modified scores is now [12, 24, 32, 12, 20, 28]
登录后复制

在 Python 3 中,map 函数返回的 map 对象可被类型转换为 list,以方便使用。现在,我们无需显式地定义 multiply_by_four 函数,而是定义 lambda 表达式:

modified_scores = list(map(lambda x: 4 * x, scores))
登录后复制

当我们想对集合内的所有值执行某项操作时,map 函数很有用。

Filter

就像名称所显示的那样,filter 函数可以帮助筛除不想要的项。例如,我们想要去除 scores 中的奇数,那么我们可以使用 filter:

even_scores = list(filter(lambda x: True if (x % 2 == 0) else False, scores))
#even_scores = [6, 8]
登录后复制

由于提供给 filter 的函数是逐个决定是否接受每一个项的,因此该函数必须返回 bool 值,且该函数必须是一元函数(即只使用一个输入参数)。

Reduce

reduce 函数用于「总结」或「概述」数据集。例如,如果我们想要计算所有分数的总和,就可以使用 reduce:

sum_scores = reduce((lambda x, y: x + y), scores)
#sum_scores = 32
登录后复制

这要比写循环语句简单多了。注意:提供给 reduce 的函数需要两个参数:一个表示正在接受检查的项,另一个表示所用运算的累积结果。

以上是一文详尽 Python 函数式编程技术的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

C语言 sum 的作用是什么? C语言 sum 的作用是什么? Apr 03, 2025 pm 02:21 PM

C语言中没有内置求和函数,需自行编写。可通过遍历数组并累加元素实现求和:循环版本:使用for循环和数组长度计算求和。指针版本:使用指针指向数组元素,通过自增指针遍历高效求和。动态分配数组版本:动态分配数组并自行管理内存,确保释放已分配内存以防止内存泄漏。

谁得到更多的Python或JavaScript? 谁得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript开发者的薪资没有绝对的高低,具体取决于技能和行业需求。1.Python在数据科学和机器学习领域可能薪资更高。2.JavaScript在前端和全栈开发中需求大,薪资也可观。3.影响因素包括经验、地理位置、公司规模和特定技能。

H5页面制作是否需要持续维护 H5页面制作是否需要持续维护 Apr 05, 2025 pm 11:27 PM

H5页面需要持续维护,这是因为代码漏洞、浏览器兼容性、性能优化、安全更新和用户体验提升等因素。有效维护的方法包括建立完善的测试体系、使用版本控制工具、定期监控页面性能、收集用户反馈和制定维护计划。

distinctIdistinguish有关系吗 distinctIdistinguish有关系吗 Apr 03, 2025 pm 10:30 PM

distinct 和 distinguish 虽都与区分有关,但用法不同:distinct(形容词)描述事物本身的独特性,用于强调事物之间的差异;distinguish(动词)表示区分行为或能力,用于描述辨别过程。在编程中,distinct 常用于表示集合中元素的唯一性,如去重操作;distinguish 则体现在算法或函数的设计中,如区分奇数和偶数。优化时,distinct 操作应选择合适的算法和数据结构,而 distinguish 操作应优化区分逻辑效率,并注意编写清晰可读的代码。

如何理解 C 语言中的 !x? 如何理解 C 语言中的 !x? Apr 03, 2025 pm 02:33 PM

!x 的理解!x 是 C 语言中的逻辑非运算符,对 x 的值进行布尔取反,即真变假,假变真。但要注意,C 语言中真假由数值而非布尔类型表示,非零视为真,只有 0 才视为假。因此,!x 对负数的处理与正数相同,都视为真。

C语言中 sum 是什么意思? C语言中 sum 是什么意思? Apr 03, 2025 pm 02:36 PM

C语言中没有内置的sum函数用于求和,但可以通过以下方法实现:使用循环逐个累加元素;使用指针逐个访问并累加元素;对于大数据量,考虑并行计算。

如何获取58同城工作页面上的实时申请和浏览人数数据? 如何获取58同城工作页面上的实时申请和浏览人数数据? Apr 05, 2025 am 08:06 AM

如何在爬虫时获取58同城工作页面的动态数据?在使用爬虫工具爬取58同城的某个工作页面时,可能会遇到这样�...

PS一直显示正在载入是什么原因? PS一直显示正在载入是什么原因? Apr 06, 2025 pm 06:39 PM

PS“正在载入”问题是由资源访问或处理问题引起的:硬盘读取速度慢或有坏道:使用CrystalDiskInfo检查硬盘健康状况并更换有问题的硬盘。内存不足:升级内存以满足PS对高分辨率图片和复杂图层处理的需求。显卡驱动程序过时或损坏:更新驱动程序以优化PS和显卡之间的通信。文件路径过长或文件名有特殊字符:使用简短的路径和避免使用特殊字符。PS自身问题:重新安装或修复PS安装程序。

See all articles