Python函数式编程的用法详解
作者:陆理手记 发布时间:2021-12-21 16:16:15
1.纯函数
纯函数是指不产生副作用的函数,即只依赖于输入参数并返回输出结果,而不修改任何外部状态。纯函数通常易于测试、可组合和并发执行。例如,下面是一个非纯函数:
total = 0
def add(n):
global total
total += n
return total
这个函数会修改total全局变量,因此是有副作用的。相反,下面是一个纯函数:
def add(n):
return n + 1
这个函数只依赖于输入参数并返回输出结果,没有任何副作用。
2.函数是一等公民
在函数式编程中,函数是一等公民。这意味着函数可以像其他数据类型一样传递给其他函数,也可以从其他函数中返回。例如:
def apply(func, arg):
return func(arg)
def double(x):
return x * 2
print(apply(double, 5)) # 输出 10
在这个例子中,我们定义了一个名为apply
的函数,它接受两个参数:一个函数和一个参数。它将这个参数传递给这个函数并返回结果。
3.高阶函数
高阶函数是指接受一个或多个函数作为参数和/或返回一个函数的函数。Python提供了许多内置的高阶函数,如map
,filter
和reduce
。例如:
# map
def square(x):
return x ** 2
numbers = [1, 2, 3, 4, 5]
squares = list(map(square, numbers))
print(squares) # 输出 [1, 4, 9, 16, 25]
# filter
def is_even(x):
return x % 2 == 0
numbers = [1, 2, 3, 4, 5]
evens = list(filter(is_even, numbers))
print(evens) # 输出 [2, 4]
# reduce
from functools import reduce
def add(x, y):
return x + y
numbers = [1, 2, 3, 4, 5]
sum = reduce(add, numbers)
print(sum) # 输出 15
在这个例子中,我们定义了三个函数:square
,is_even
和add
。然后,我们使用内置的高阶函数map
,filter
和reduce
来对数字列表进行操作。
4.Lambda表达式
Lambda表达式是一种匿名函数,可以用来定义简单的函数。它们通常在需要一个函数作为参数的地方使用。例如:
numbers = [1, 2, 3, 4, 5]
squares = list(map(lambda x: x ** 2, numbers))
print(squares) # 输出 [1, 4, 9, 16, 25]
evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens) # 输出 [2, 4]
在这个例子中,我们使用Lambda表达式来定义map
和filter
函数的函数参数。
5.偏函数
偏函数是指通过部分设置参数来创建新函数的过程。在Python中,我们可以使用functools.partial函数来实现偏函数。偏函数是一种指定部分参数的函数。例如,假设有一个函数:
def power(base, exponent):
return base ** exponent
如果要计算2
的平方和立方,可以这样实现:
print(power(2, 2))
print(power(2, 3))
输出:
4
8
使用偏函数可以更方便地计算多个指数。例如:
from functools import partial
square = partial(power, exponent=2)
cube = partial(power, exponent=3)
print(square(2))
print(cube(2))
输出:
4
8
这里使用了functools.partial
函数将power
函数的exponent
参数固定为2
或3
,从而创建了两个新的函数square
和cube
。
6.函数组合
函数组合是指将多个函数组合成一个函数。例如,假设有两个函数:
def add1(n):
return n + 1
def double(n):
return n * 2
现在要实现一个新函数,将add1
和double
组合起来,可以这样实现:
def compose(f, g):
return lambda x: f(g(x))
add1_double = compose(add1, double)
print(add1_double(3))
输出:
7
这个函数首先将输入参数3
传递给double
函数,然后将其结果6
传递给add1
函数,最终得到7
。
7.不可变性
函数式编程鼓励不可变性,尽量减少或避免可变状态和副作用。这可以通过使用元组、冻结集合和不可变对象来实现。例如:
# 元组
person = ('John', 25)
name, age = person
# 冻结集合
my_set = frozenset([1, 2, 3])
# 不可变对象
from collections import namedtuple
Person = namedtuple('Person', ['name', 'age'])
person = Person(name='John', age=25)
在这个例子中,我们使用元组、冻结集合和不可变对象来创建不可变数据结构。
8. 尾递归优化
尾递归是指函数的最后一个操作是它自己的递归调用。这可以通过迭代实现,并且可以避免堆栈溢出错误。Python没有尾递归优化,但可以使用生成器和迭代器来模拟。尾递归优化是一种技术,它可以将递归函数的调用栈优化为迭代循环,从而减少内存占用和提高程序性能。
在 Python 中实现尾递归优化有两种方法:
使用 sys.setrecursionlimit() 函数增加最大递归深度。
实现一个尾递归函数,并使用一个 while 循环替换递归调用。
以下是一个简单的例子:
import sys
sys.setrecursionlimit(10000)
def factorial(n, acc=1):
if n == 0:
return acc
else:
return factorial(n-1, acc*n)
def tail_recursion_factorial(n, acc=1):
while n > 0:
n, acc = n-1, acc*n
return acc
在这个例子中,我们定义了两个函数:factorial
和 tail_recursion_factorial
。factorial
是一个正常的递归函数,而 tail_recursion_factorial
是一个尾递归函数。
如果使用 factorial(1000)
这样的参数调用 factorial
函数,将会产生 RecursionError
,因为默认情况下 Python
的最大递归深度为1000
。为了解决这个问题,我们增加了最大递归深度并重新运行代码。
使用 tail_recursion_factorial(1000)
来调用 tail_recursion_factorial
函数,则不会出现RecursionError
,因为该函数被优化为迭代循环。
需要注意的是,尾递归优化并不总是有效,因为有时候需要保留函数调用栈以便于在返回时执行一些操作。此外,在 Python
中默认情况下并没有进行尾递归优化,因此需要手动实现它。
9.总结
Python函数式编程是一种编程范式,它的核心思想是将计算视为数学函数的运算,并且避免使用可变状态和副作用。在这篇教程总结中,我们将讨论如何使用Python进行函数式编程。
第一步是理解函数是什么。在函数式编程中,函数被认为是“一等公民”,这意味着它们可以像任何其他数据类型一样传递和操作。因此,函数通常会接受输入并返回输出,而不会修改状态或影响外部环境。
然后,我们需要了解Python中的lambda表达式。Lambda表达式是一种匿名函数,它可以在需要时方便地定义和调用。它的语法类似于“lambda arguments: expression”,其中arguments是参数列表,expression是函数体。
接下来是高阶函数。在函数式编程中,高阶函数是指接受一个或多个函数作为参数的函数,或者返回一个新函数的函数。例如,map()函数可以接受一个函数和一个序列,并返回一个新序列,其中每个元素都是通过应用给定函数得到的结果。
还有一个重要的概念是闭包。闭包是指一个函数内部定义的函数,它可以访问其外部函数的变量和参数。这使得我们可以创建一些特殊的函数,例如currying和partial functions。
此外,函数式编程还涉及到一些常见的函数,例如filter()、reduce()和sorted()。这些函数可以帮助我们在Python中进行函数式编程。
最后,我们需要了解如何避免使用可变状态和副作用。这意味着我们应该尽可能避免修改对象的状态或影响外部环境。相反,我们应该尝试编写纯函数,这些函数只依赖于其输入,并且不会修改状态或引起副作用。
总之,在Python中进行函数式编程需要掌握lambda表达式、高阶函数、闭包以及避免使用可变状态和副作用等概念。通过这些技术,我们可以创建更具可读性、可维护性和可重用性的代码。
来源:https://juejin.cn/post/7240374267694219322


猜你喜欢
- 池化层定义在tensorflow/python/layers/pooling.py.有最大值池化和均值池化。1、tf.layers.max_
- Python中yaml文件的读写(使用PyYAML库)。最近在搭建自动化测试项目过程中经常遇到yaml文件的读写,为了方便后续使用,决定记下
- 在查看Mysql对文件的操作中,它在不同的操作系统上对文件的操作,除了使用标准C运行库函数,包括open、close、seek等,在Win3
- 1.开发jQuery 插件的基本格式 (function ($) { $.extend($.fn, { }) })(jQuery) 2.开发
- 容器与可迭代对象在正式开始前先补充一些基本概念在 Python 中存在容器 与 可迭代对象容器:用来存储多个元素的数据结构,例如 列表,元组
- 项目简介之前学python的时候 写了个游戏来练手 用的是 pygame 没有别的依赖只用了一两百行的代码就实现了 整体来说功能并不算完整项
- 一、简单优化1.图片纹理大小尽量为2的幂次方(比如128,512,1024等等),以便unity对其进行优化。2.将多个小图片纹理合并一个大
- 下面代码写的是js验证检查输入的字符是否是全角的函数:效果演示:<script> function i
- 语法格式如下:assert expression等价于:if not expression: raise AssertionErrorass
- Python类基本写法与注释风格python是一种面向对象的语言,利用类的抽象可以大大提高代码的复用和结构,减少重复造轮子的过程,也让代码变
- 摘要With the continuous development of time series prediction, Transform
- 本文实例为大家分享了js选项卡切换的具体代码,可以手动切换,另设置定时器可使其自动切换,供大家参考,具体内容如下效果如图:具体代码:<
- 1、一些准备工作 安装djangopip install django创建django项目进入项目代码存放目录执行命令:djang
- #coding=utf-8__auther__ = 'xianbao'import sqlite3# 打开数据库def op
- 参考资料:正则表达式语法–菜鸟教程Java正则表达式实现简单批量替换举例:将and 批量替换为&&Python实现impor
- 前言深度学习涉及很多向量或多矩阵运算,如矩阵相乘、矩阵相加、矩阵-向量乘法等。深层模型的算法,如BP,Auto-Encoder,CNN等,都
- 本文实例讲述了thinkPHP框架通过Redis实现增删改查操作的方法。分享给大家供大家参考,具体如下:一、概述Redis是一个NoSQL数
- Python基本输入和输出1.input输入函数input函数:获取用户输入,保存成一个字符串。>>> name = in
- 如下所示:import time首先导入时间模块在程序开始执行的地方写入:start=time.clock()在程序末尾写入:end=tim
- 窗口程序的开发流程如下:1. 先通过qt designer设置界面并将程序图标设置好,通过在designer中按ctrl + R 进行预览可